home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacTech 1 to 12
/
MacTech-vol-1-12.toast
/
Reference
/
the cmsp digests ('94-'97)
/
csmp digest Vol 3 No 144
< prev
next >
Wrap
Text File
|
1996-04-16
|
136KB
|
3,647 lines
C.S.M.P. Digest Mon, 15 Apr 96 Volume 3 : Issue 144
Today's Topics:
68K or PPC struct alignment?
Apple's Game API
CopyBits-Yet again I ask
Determining Memory Size Needed by GWorld
Direct-Optimized Access to PixMap
Display Manager
Fast writes to disk?
How should data be organized for read-write to files?(beginner)
How to Do Registration Codes
How to find CTB devices ?
How to make an app scriptable
Macsbug 6.5.3 slower at stepping?
NewGWorld Memory Leak?
Optimizing RGB pixel operations on PPC?
UMPA Awards Last week for Nominations
[ANN] MoreFiles v1.4.2 now available
[Q] Selecting a Serial Port
The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
(pottier@clipper.ens.fr).
The digest is a collection of article threads from the internet
newsgroups comp.sys.mac.programmer.help, csmp.tools, csmp.misc and
csmp.games. It is designed for people who read news semi-regularly and
want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. If you don't have access to news, you
may still be able to post messages to the group by using a mail server
like anon.penet.fi (mail help@anon.penet.fi for more information).
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
nef.ens.fr). Article threads are not added to the digest until the last
article added to the thread is at least two weeks old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The digest is officially distributed by two means, by email and ftp.
If you want to receive the digest by mail, send email to listserv@ens.fr
with no subject and one of the following commands as body:
help Sends you a summary of commands
subscribe csmp-digest Your Name Adds you to the mailing list
signoff csmp-digest Removes you from the list
Once you have subscribed, you will automatically receive each new
issue as it is created.
The official ftp info is ftp://ftp.dartmouth.edu/pub/csmp-digest.
Questions related to the ftp site should be directed to
scott.silver@dartmouth.edu.
-------------------------------------------------------
>From timmyd@netcom.com (Tim DeBenedictis)
Subject: 68K or PPC struct alignment?
Date: Thu, 28 Mar 1996 23:03:34 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
Hi everybody-
I'm wriring a program which needs to read some data files on both 68K and
PowerPC Macs. Since the guy who wrote the program was not clever enough
to make his structs come out the with the same size and byte alignment on
both platforms :), I need to make CodeWarrior choose either 68K or PPC
struct alignment to make things work without crashing.
I know that the PowerPC, especially 603 and 604, are very sensitive to
bad byte alignment in terms of performance. However, if I choose PPC
struct alignment, will my 68K versions suffer a great performance hit?
And will the reverse be true if I choose 68K struct alignment?
Thanks in advance,
-Tim DeBenedictis
timmyd@netcom.com
+++++++++++++++++++++++++++
>From "Andrew C. Plotkin" <erkyrath+@CMU.EDU>
Date: Fri, 29 Mar 1996 01:53:29 -0500
Organization: Carnegie Mellon, Pittsburgh, PA
timmyd@netcom.com (Tim DeBenedictis) writes:
> I'm wriring a program which needs to read some data files on both 68K and
> PowerPC Macs. Since the guy who wrote the program was not clever enough
> to make his structs come out the with the same size and byte alignment on
> both platforms :), I need to make CodeWarrior choose either 68K or PPC
> struct alignment to make things work without crashing.
>
> I know that the PowerPC, especially 603 and 604, are very sensitive to
> bad byte alignment in terms of performance. However, if I choose PPC
> struct alignment, will my 68K versions suffer a great performance hit?
PPC alignment is more aligned than 68K alignment. I mean, more things
will be aligned to 4-byte boundaries in PPC than 68K, if you see what
I mean, and so on.... So a 68K program will never take a speed hit
because of PPC alignment. However, the structs will be bigger, so you
take a memory hit. (I suppose this could impact the speed, too,
because the data cache will fill up faster -- but this is really not
worth worrying about until it's *really* necessary.)
> And will the reverse be true if I choose 68K struct alignment?
A PPC program will take a speed hit if you give it 68K alignment.
However, the difference may be unnoticeable. Do some tests.
You can also use #pragmas to align particular structure types to 68K
alignment, when the rest of the program is in PPC alignment. This
lessens the speed hit, obviously. This is often a good idea,
especially if those structs are only used in a few places.
--Z
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
+++++++++++++++++++++++++++
>From Keith Wiley <keithw@wam.umd.edu>
Date: Fri, 29 Mar 1996 10:27:33 -0500
Organization: University of Maryland College Park
> I'm wriring a program which needs to read some data files on both 68K and
> PowerPC Macs. Since the guy who wrote the program was not clever enough
> to make his structs come out the with the same size and byte alignment on
> both platforms :), I need to make CodeWarrior choose either 68K or PPC
> struct alignment to make things work without crashing.
How is this done? Is it a compiler switch in the preferences, a .h file
of some sort, or do I need to actually learn new C code in order to
utilize this?
> I know that the PowerPC, especially 603 and 604, are very sensitive to
> bad byte alignment in terms of performance. However, if I choose PPC
> struct alignment, will my 68K versions suffer a great performance hit?
I'd like to know how it affects the 601 if anyone knows. This is
probably my problem.
. . .. ... ..... ........ ............. .....................
.. ... ..... ....... ........... ............. .................
. .. .... ........ ................ ................................
Keith Wiley, Electrogenetic Engineer *
University of Maryland at College Park * * * * * *
email: keithw@wam.umd.edu *** ** * * ** *
world wide web: http://www.wam.umd.edu/~keithw * ** ** ***
+++++++++++++++++++++++++++
>From tonyn@tiac.net (Tony Nelson)
Date: Mon, 01 Apr 1996 10:52:27 -0500
Organization: The Internet Access Company
In article <timmydDp02pz.EGv@netcom.com>, timmyd@netcom.com (Tim
DeBenedictis) wrote:
> I'm wriring a program which needs to read some data files on both 68K and
> PowerPC Macs. Since the guy who wrote the program was not clever enough
> to make his structs come out the with the same size and byte alignment on
> both platforms :), I need to make CodeWarrior choose either 68K or PPC
> struct alignment to make things work without crashing.
All you need is to be able to read those brain-damaged files correctly.
Just declare two sets of types, using appropriate filler to get things in
the right place, wrapping the type declarations in the appropriate pragma
options align directives. See Apple's header files and the CodeWarrior
C/C++/Asm Lang Ref. Leave the rest of your program (all the internal
stuff) at native alignment. Pick one of the alignments when you write
files, or write everything byte-by-byte (usually big-end first so you can
assemble words and longs with just shift and or) so the file isn't machine
specific.
____________________________________________________________________
TonyN.:' tonyn@tiac.net
'
---------------------------
>From brianm@caledonia.polaristel.net (Brian P. McCarty)
Subject: Apple's Game API
Date: Tue, 26 Mar 1996 13:13:09 -0600
Organization: totally disorganized
If haven't read it, I suggest you look at MacWEEK's article on Apple's
game API. You can get it at
http://www.zdnet.com/macweek/mw_1012/news_game_makers.html
The article mentions a apple games site at http://dev.info.apple.com/games
when I went there it said it would be open March 31.
(it actually took me to http://dev.info.apple.com/evangelism/games/games.html)
I tried the macweek address mar 26 and it was too busy, I did connect on
March 25. The apple site did display on March 26 (your milage may vary)
Brian
--
Brian P. McCarty, N9IWP
e-mail:brianm@caledonia.polaristel.net
snail-mail:410 S. Ramsey, Apt. 4 Caledonia, MN 55921-1116
ICBM:43deg 38' 05" N 91deg 29' 48" W
---------------------------
>From Brewski@twics.com (Brian Sweeney)
Subject: CopyBits-Yet again I ask
Date: 23 Mar 1996 15:33:45 GMT
Organization: All USENET -- www.net-link.com
I have read the books,downloaded the technical notes from apple etc but I cannot
find the reason why my Copybits routine copying from a PixMap to a GWorld works
on Non-Power Macintoshes but does not copy properly on a Power Mac.
Both the srcRect and the DstRect are the same size ,Both PixMaps are 256 colors
and the transfer mode is SrcCpy.And it works on Non-Power Macs.
Has anybody out there have an inkling of what could cause the Copybits
routine to differ between Non power Macs and Power Macs.
Better yet ,if anybody has a simple code snippet of copying a dummy pixmap
to a GWorld that works on a Power Mac I would be eternally grateful.
+++++++++++++++++++++++++++
>From heaney@crl.com (John S. Heaney)
Date: 23 Mar 1996 13:44:19 -0800
Organization: CRL Dialup Internet Access (415) 705-6060 [Login: guest]
In article <Brewski-2303962352230001@c12.dial.twics.com>,
Brian Sweeney <Brewski@twics.com> wrote:
>I have read the books,downloaded the technical notes from apple etc but I cannot
>find the reason why my Copybits routine copying from a PixMap to a GWorld works
>on Non-Power Macintoshes but does not copy properly on a Power Mac.
>Both the srcRect and the DstRect are the same size ,Both PixMaps are 256 colors
>and the transfer mode is SrcCpy.And it works on Non-Power Macs.
>Has anybody out there have an inkling of what could cause the Copybits
>routine to differ between Non power Macs and Power Macs.
I had a similar situation to yours, although there's not enough
information here to know how similar. I was fading down one graphic and
fading up another. I faded down all 256 colors, drew the new graphics,
and faded up to the new clut. This technique relies on no color mapping
taking place when the new graphics are drawn because all the colors are
black. So, I did the ctSeed slam when drawing all my graphics.
This worked fine on my 68K machine, but failed when I ran the same 68K
application on a PowerMac. Note I am not talking about a native
application, but emulated. It drove me crazy until I found out that a bug
in my code was preventing the ctSeed slam from happening. Even so, it was
working on the 68K machine, but not on the PowerMac.
I really don't know what that means beyond the apparent fact that the two
platforms seem to differ in how they do color mapping. I don't know if
it's the onboard video or what. It may have even been the system version;
I was using 7.1 on the 68K machine and 7.5 on the PowerMac.
The whole color mapping thing is a bit of voodoo, as far as I can see.
For example, I've still yet to determine how to fade to pure black, draw
my new graphics and fade up to the new colors. I actually fade down to
almost black (256, 256, 256). This works fine except you can still see
the image if you turn the brightness of your monitor way up.
It seems that if I fade to pure black then the Color Manager sees the
first black as the end of the palette, which it isn't, of course. It then
seems to remap the colors of the new graphics to the same color black,
probably the first one. Then when the colors fade up, you get a white
screen or some other color mapping problem. It's pretty weird.
>Better yet ,if anybody has a simple code snippet of copying a dummy pixmap
>to a GWorld that works on a Power Mac I would be eternally grateful.
I program in Prograph, so it probably wouldn't do you much good. See if
any of this resonates with you and maybe you'll find some relevant details
of your code that you could post. Maybe we'll get to the root of it
someday. :)
--
John Heaney Time flies whether you're having fun or not.
heaney@crl.com
+++++++++++++++++++++++++++
>From 'Digital Dave' Shields <digidave@vvstudios.com>
Date: Mon, 25 Mar 1996 06:03:42 -0800
Organization: Vanguard Vision Studios, San Francisco, CA
Brian Sweeney wrote:
>
> I have read the books,downloaded the technical notes from apple etc but I cannot
> find the reason why my Copybits routine copying from a PixMap to a GWorld works
> on Non-Power Macintoshes but does not copy properly on a Power Mac.
> Both the srcRect and the DstRect are the same size ,Both PixMaps are 256 colors
> and the transfer mode is SrcCpy.And it works on Non-Power Macs.
> Has anybody out there have an inkling of what could cause the Copybits
> routine to differ between Non power Macs and Power Macs.
Well, using CopyBits from/to GWorlds are supposed to be done by
dereferencing and locking the handle you get from GetGWorldPixMap()...
not from dereferencing the GWorld Handle. Some people don't know that,
and it causes a lot of problems...What I mean is:
THE WRONG WAY (which can work sometimes but not always):
CopyBits (((CGrafPtr)pGWorld)->portPixMap,
((CGrafPtr)pWindow)->portPixMap,
rSourceRect,
rDestRect,
srcCopy,
nil);
A BETTER WAY (leaving out error checking, etc.):
hGWorldPixMap = GetGWorldPixMap (pGWorld);
LockPixels (hGWorldPixMap);
CopyBits ( *hGWorldPixMap,
((CGrafPtr)pWindow)->portPixMap,
rSourceRect,
rDestRect,
srcCopy,
nil);
UnlockPixels (hGWorldPixMap);
...just a suggestion...
--Dave
+++++++++++++++++++++++++++
>From Martin_Byrod@digit.se (Martin Byrod)
Date: 26 Mar 1996 14:05:47 GMT
Organization: Digit
I was fading down one graphic and
fading up another. I faded down all 256 colors, drew the new graphics,
and faded up to the new clut.
Please post to this newsgroup and tell me how you faded your graphics.
I really need to learn how to do that!!!
thanx in advance,
Martin
+++++++++++++++++++++++++++
>From carl.gustafson@ece.drexel.edu (Carl Gustafson)
Date: Tue, 26 Mar 1996 08:45:44 -0500
Organization: Imaging and Computer Vision Center, Drexel University
In article <Brewski-2303962352230001@c12.dial.twics.com>,
Brewski@twics.com (Brian Sweeney) wrote:
> I have read the books,downloaded the technical notes from apple etc but
I cannot
> find the reason why my Copybits routine copying from a PixMap to a
GWorld works
> on Non-Power Macintoshes but does not copy properly on a Power Mac.
> Both the srcRect and the DstRect are the same size ,Both PixMaps are 256
colors
> and the transfer mode is SrcCpy.And it works on Non-Power Macs.
> Has anybody out there have an inkling of what could cause the Copybits
> routine to differ between Non power Macs and Power Macs.
>
> Better yet ,if anybody has a simple code snippet of copying a dummy pixmap
> to a GWorld that works on a Power Mac I would be eternally grateful.
I was having problems copybitsing from GWorld to GWorld - it would result
in a quick
trip to Macsbug. Copy from GWorld to screen (PixMap) would run just fine.
Never tried
the reverse - the screen is just to display the image, and we always go
from image
data to screen, never the reverse. ANYWAY, I finally traced it down to not
having a
GrafPort or GWorld set, believe it or not. Once I made a call to
SetGWorld, things
worked fine.
FWIW, HTH, YMMV, ETC.
--
Carl Gustafson
Imaging and Computer Vision Center
Drexel University, Philadelphia, Penna
- ----------------------------------------------------------
I don't speak for Drexel, and Drexel doesn't listen to me...
---------------------------
>From at@neuro.psy.soton.ac.uk (Adriaan Tijsseling)
Subject: Determining Memory Size Needed by GWorld
Date: Mon, 25 Mar 1996 07:30:01 +0000
Organization: Electronics and Computer Science, University of Southampton
Hi,
How can I determine how much memory a GWorld with a given width and height
needs? It is useful to compare this to the amount of free memory in my app
before I call NewGWorld.
If you know how, mail or post it,
Many thanks in advance,
Adriaan Tijsseling
______________________________________________________________
Work:
Cognitive Sciences Centre
Department of Psychology
University of Southampton
United Kingdom
Homepages:
work: http://www.soton.ac.uk/~coglab/coglab
life: http://www.soton.ac.uk/~agt/
E-mail:
at@neuro.psy.soton.ac.uk
at@cogsci.ecs.soton.ac.uk
agt@oak.soton.ac.uk
______________________________________________________________
+++++++++++++++++++++++++++
>From pottier@drakkar.ens.fr (Francois Pottier)
Date: 25 Mar 1996 14:58:07 GMT
Organization: Ecole Normale Superieure, Paris
In article <at-2503960730010001@sm1.psy.soton.ac.uk>,
Adriaan Tijsseling <at@neuro.psy.soton.ac.uk> wrote:
>How can I determine how much memory a GWorld with a given width and height
>needs? It is useful to compare this to the amount of free memory in my app
>before I call NewGWorld.
There is no way to determine it other than guessing. The main
component of a GWorld is its pixmap, so compute an approximation of
its size by multiplying depth, height and width. Then, as a rule of
thumb, add 15K for color tables, inverse tables, graphics device and
other mysterious more-or-less-documented stuff.
Anyway, you should check NewGWorld's return code and exit gracefully
it it different from noErr. You don't need to check the result for
nil; the rumor that NewGWorld might return noErr and nil is, as far as
I know, a myth fed by Object Pascal programmers forgetting to call
HLock(Self). Anyway, checking for nil can't hurt.
Also, you can ask NewGWorld to allocate the pixmap in the temporary
memory zone by setting a flag. If you do that, only the auxiliary
structures will be allocated in your heap.
Hope this helps,
--
Francois Pottier
Francois.Pottier@ens.fr
Francois.Pottier@inria.fr
http://www.eleves.ens.fr:8080/home/pottier/
+++++++++++++++++++++++++++
>From cameron_esfahani@powertalk.apple.com (Cameron Esfahani)
Date: Tue, 26 Mar 1996 08:28:11 GMT
Organization: Apple Computer, Inc.
Actually, a good idea is to nil out your gworldptr you pass to NewGWorld
and if you don't get an error from NewGWorld compare compare the returned
gworldptr to nil. There are some error cases in NewGWorld where Quickdraw
will bail out without returning an error.
Cameron Esfahani
---------------------------
>From fettig@cloister (Thomas Fettig)
Subject: Direct-Optimized Access to PixMap
Date: 23 Mar 1996 15:03:48 GMT
Organization: DFKI - German Research Center for Artificial Intelligence
Hello experts,
I am looking for information on how to manipulate the
PixMap of an Offscreen GWorld directly. What i have is
a piece of memory containing image data in 256 colors.
When i construct the Pixmap by going through SetPixel,
large images take a few seconds to convert. This seems
to much to me. How may i access the PixMap in a
system-conforming way? (ie. Byte offsets, color values, etc)
A pointer to a book or source-code would be fine too!
tia,
tom
+++++++++++++++++++++++++++
>From bzuk@telerama.lm.com (Brian Zuk)
Date: Sat, 23 Mar 1996 17:10:19 -0500
Organization: Telerama Public Access Internet, Pittsburgh, PA
In article <FETTIG.96Mar23160348@cloister>, fettig@cl.dfki.uni-sb.de wrote:
>Hello experts,
>
>I am looking for information on how to manipulate the
>PixMap of an Offscreen GWorld directly. What i have is
>a piece of memory containing image data in 256 colors.
>When i construct the Pixmap by going through SetPixel,
>large images take a few seconds to convert. This seems
>to much to me. How may i access the PixMap in a
>system-conforming way? (ie. Byte offsets, color values, etc)
>A pointer to a book or source-code would be fine too!
>
>tia,
> tom
Tom,
The safest/easiest approach for you is to construct a PixMapHandle that
matches your cached data. Then call CopyBits using the built PixMapHandle
as the source and the GWorld as the dest pixMaps.
If you really want to move the data directly into the GWorld, you can
copy bytes of information from one PixMap to the other by getting the base
address from both of the pixMaps, determining how many bytes to move, and
then moving them using a loop or BlockMove. Any game programming book
will have specific details of how to do this.
Feel free to e-mail me directly for any specific information.
Brian Zuk
+++++++++++++++++++++++++++
>From oo@oo.com (lisa beaufort)
Date: 24 Mar 1996 04:41:38 GMT
Organization: ooo
In article <FETTIG.96Mar23160348@cloister>, fettig@cl.dfki.uni-sb.de wrote:
> Hello experts,
>
> I am looking for information on how to manipulate the
> PixMap of an Offscreen GWorld directly. What i have is
> a piece of memory containing image data in 256 colors.
> When i construct the Pixmap by going through SetPixel,
> large images take a few seconds to convert. This seems
> to much to me. How may i access the PixMap in a
> system-conforming way? (ie. Byte offsets, color values, etc)
> A pointer to a book or source-code would be fine too!
>
> tia,
> tom
I can post some Assembly examples?
c. lisa b.
+++++++++++++++++++++++++++
>From carl.gustafson@ece.drexel.edu (Carl Gustafson)
Date: Tue, 26 Mar 1996 09:14:14 -0500
Organization: Imaging and Computer Vision Center, Drexel University
In article <FETTIG.96Mar23160348@cloister>, fettig@cl.dfki.uni-sb.de wrote:
> I am looking for information on how to manipulate the
> PixMap of an Offscreen GWorld directly. What i have is
> a piece of memory containing image data in 256 colors.
> When i construct the Pixmap by going through SetPixel,
> large images take a few seconds to convert. This seems
> to much to me. How may i access the PixMap in a
> system-conforming way? (ie. Byte offsets, color values, etc)
> A pointer to a book or source-code would be fine too!
Get a copy of the PixMapHandle from your GWorld, then extract the rowBytes
field. Strip the high two bits to give you width (row spacing) of the
pixel image. Then call LockPixels (), and get the base address using
GetPixBaseAddr (). You can now directly address the pixels in your GWorld
by computing offsets from the base address. Be sure to use long math!
long h,v,offset,width,height;
short rowBytes;
unsigned char *pixBase, pixel;
rowBytes = (**thePixMap).rowBytes & 0x3FFF;
LockPixels (thePixMap);
pixBase = (unsigned char *) GetPixBaseAddr (thePixMap);
width = (**thePixMap).bounds.right - (**thePixMap).bounds.left;
width = (**thePixMap).bounds.bottom - (**thePixMap).bounds.top;
for (v = 0; v < height; v++)
{
offset = v * rowBytes;
for (h = 0; h < width; h++)
{
pixel = *(pixBase + offset + h);
...
etc
...
}
}
--
Carl Gustafson
Imaging and Computer Vision Center
Drexel University, Philadelphia, Penna
- ----------------------------------------------------------
I don't speak for Drexel, and Drexel doesn't listen to me...
---------------------------
>From matthewf@panix.com (Matthew)
Subject: Display Manager
Date: Mon, 25 Mar 1996 09:40:52 -0500
Organization: PANIX Public Access Internet and Unix, NYC
I seem to remember someone posting that DM will handle removing and
restoring the menubar for game programmers who want to write to the full
screen and still be compatable with future Macs. But now I cant find any
info on this in the DM Developer Notes, so I might have imagined this.
If anyone knows if this is true or not please let me know.
thanks
Matthew
+++++++++++++++++++++++++++
>From Maf Vosburgh <maf@mmcorp.com>
Date: 25 Mar 1996 18:14:10 GMT
Organization: MultiMedia Corporation plc
In article <matthewf-2503960940530001@matthewf.dialup.access.net>
Matthew, matthewf@panix.com writes:
>I seem to remember someone posting that DM will handle removing and
>restoring the menubar for game programmers who want to write to the full
>screen and still be compatable with future Macs. But now I cant find any
>info on this in the DM Developer Notes, so I might have imagined this.
>
This is handled by a couple of QuickTime 2.1 calls, BeginFullScreen and
EndFullScreen.
It's a very nice simle API. It will do screen resolution switching for
you as well.
The Display Manager is a real dog - there are various different version
to worry about, and the complex inter-connected data structures and
callback procs will make your head spin.
Maf
+++++++++++++++++++++++++++
>From dalawren@netcom.com (David Lawrence)
Date: Sat, 30 Mar 1996 13:12:25 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
In article <matthewf-2503960940530001@matthewf.dialup.access.net>,
matthewf@panix.com (Matthew) wrote:
> I seem to remember someone posting that DM will handle removing and
> restoring the menubar for game programmers who want to write to the full
> screen and still be compatable with future Macs. But now I cant find any
> info on this in the DM Developer Notes, so I might have imagined this.
>
> If anyone knows if this is true or not please let me know.
There is a pair of QuickTime 2.1 calls - BeginFullScreen() and
EndFullScreen() that will switch to a requested monitor resolution (if
possible), hide the menu bar, and create a full screen window. I believe
it uses Display Manager 2.0 to switch resolutions - it won't switch if DM
2.0 is not installed. Menu bar hiding is not part of Display Manager.
David Lawrence
Future Tense
---------------------------
>From srharris@tucson.princeton.edu (Scott R. Harris)
Subject: Fast writes to disk?
Date: 5 Mar 1996 03:41:05 GMT
Organization: Princeton University
I've got a scientific frame grabber installed in my powermac 7500 and I want to
capture 640x480x8 bit images and save them to disk as quickly as possible.
What's the fastest way to write the data to the disk? I tried using fopen and
fwrite and i can get about 700K per second, but I want to go faster. Are the
macOS file routines faster (I'm going to try them tonight)?
Will an AV drive make a difference (I have the 1 gig drive that came with the
computer)? Are there lower level routines that are faster? Will speed
doubler help? What about cache? I've also thought about using quicktime to
compress my images first, hopefully the time a i spend compressing will be
made up for in the time i spend writing to disk.
Anyhow, If I can get a sustained rate of about 3 Meg/second, I can do my
experiment in a really elegant way.
Thanks for any help,
-Scott Harris
Department of Mechanical and Aerospace Engineering, Princeton University
+++++++++++++++++++++++++++
>From grinch@buffnet.net (The Grinch)
Date: 6 Mar 1996 20:23:35 GMT
Organization: Vortex Software
In article <4hgd4h$3qh@cnn.Princeton.EDU>, srharris@tucson.princeton.edu
(Scott R. Harris) wrote:
> I've got a scientific frame grabber installed in my powermac 7500 and I
want to
> capture 640x480x8 bit images and save them to disk as quickly as possible.
> What's the fastest way to write the data to the disk? I tried using fopen and
> fwrite and i can get about 700K per second, but I want to go faster. Are the
> macOS file routines faster (I'm going to try them tonight)?
I don't think lower level routines would be appreciably faster. (I mean,
how much CPU time does glue code really eat?) Using a faster HD is an
obvious choice, though. How much RAM have you got? Fair amount? Then why
not make a huge RAM disk and write to that? In an ideal situation, I'd get
my hands on a big ol' RAID 0 array, but that's not often feasible. Anyway,
that's just my 2¢. Good luck!
-The Grinch
+++++++++++++++++++++++++++
>From slasley@space.umd.edu (Scott E. Lasley)
Date: Fri, 8 Mar 1996 18:13:51 -0500
Organization: UMD Space Physics Group
In article <4hgd4h$3qh@cnn.Princeton.EDU>, srharris@tucson.princeton.edu
(Scott R. Harris) writes:
> I've got a scientific frame grabber installed in my powermac 7500 and
> I want to capture 640x480x8 bit images and save them to disk as quickly
> as possible.
> What's the fastest way to write the data to the disk? I tried using
> fopen and fwrite and i can get about 700K per second, but I want to
> go faster. Are the macOS file routines faster (I'm going to try
> them tonight)?
>
tech note FL 16 - File Manager Performance and Caching - contains a lot of
good information about getting the most out of the file manager
http://dev.info.apple.com/technotes/Archive/Files/fl_16.html
one source of good file i/o code is the MoreFiles package at
<ftp://members.aol.com//JumpLong/>
hope this helps,
scott lasley slasley@space.umd.edu, http://space.umd.edu
"Cheating is bad. Richard Basehart is good." MST3K
http://fermi.clas.virginia.edu/~jcp9j/canceled.html
+++++++++++++++++++++++++++
>From blob@ccnet.com
Date: Sun, 17 Mar 1996 11:55:04 -0800
Organization: CCnet Communications (510-988-7140 guest)
In article <4hgd4h$3qh@cnn.Princeton.EDU>, srharris@tucson.princeton.edu
(Scott R. Harris) wrote:
> I've got a scientific frame grabber installed in my powermac 7500 and I
want to
> capture 640x480x8 bit images and save them to disk as quickly as possible.
> What's the fastest way to write the data to the disk? I tried using fopen and
> fwrite and i can get about 700K per second, but I want to go faster. Are the
> macOS file routines faster (I'm going to try them tonight)?
Read tech note FL 16, at
<http://dev.info.apple.com/technotes/Archive/Files/fl_16.html>
It's all about file system performance. Basically, keep your buffers as
large as possible, use the cache wisely, bypass the cache when it makes
sense.
fopen and fwrite have buffers determined by your standard i/o library. I
doubt if they are optimized. Look at MoreFiles for better examples of
fast writes.
+++++++++++++++++++++++++++
>From tonyn@tiac.net (Tony Nelson)
Date: Sat, 23 Mar 1996 22:14:55 -0500
Organization: The Internet Access Company
In article <blob-1703961155040001@h108-5-129.ccnet.com>, blob@ccnet.com wrote:
> ... Basically, keep your buffers as
> large as possible ...
There have been some reports of problems if the reads or writes are for
more than about 1 or 2 MB at a time, with some Macs and some hard disk
drivers. I would guess that there is some sort of diminishing return
about 64..256K, so if you want you could avoid those possible problems.
You want to use async I/O. On older Macs it won't help, but new ones
should get a big performance boost as you can be grabbing and storing
simultaneously.
____________________________________________________________________
TonyN.:' tonyn@tiac.net
'
+++++++++++++++++++++++++++
>From jumplong@aol.com (Jump Long)
Date: 24 Mar 1996 14:04:49 -0500
Organization: America Online, Inc. (1-800-827-6364)
Tony Nelson wrote:
>There have been some reports of problems if the reads or writes
>are for more than about 1 or 2 MB at a time, with some Macs and
>some hard disk drivers. I would guess that there is some sort
>of diminishing return about 64..256K, so if you want you could
>avoid those possible problems.
Most of those problems are due to disk drivers not handling VM issues
correctly. However, Tony is correct that at some point, increasing the
size of your I/O operations gives very little performance gains. With
faster hard disks, that point is a smaller amount than with slower media
(floppy disks, CD-ROMs, etc.).
>You want to use async I/O. On older Macs it won't help, but new
>ones should get a big performance boost as you can be grabbing
>and storing simultaneously.
Since the File Manager is single-threaded (for the most part), multiple
async requests just execute in the order they are added the File Manager's
queue. If the device you're using supports async I/O operations, then
doing other non-I/O related tasks while waiting for the async requests to
complete is what really gives the most wins today. For example, the System
7.5.2 and 7.5.3 Finder uses async reads and writes for file copy
operations and then calls WaitNextEvent while waiting for the requests to
complete. This allows the user to perform non-I/O tasks with other
applications while the Finder is copying files.
- Jim Luther
jumplong@aol.com
<http://members.aol.com/JumpLong/>
---------------------------
>From v.salupo@lilly.com (Vince Salupo)
Subject: How should data be organized for read-write to files?(beginner)
Date: Tue, 26 Mar 1996 15:04:46 -0500
Organization: Eli Lilly and Company
Most Mac programming books deal with interface issues. I haven't run across a
clear explanation of how to do any of the following in C:
- create structures that are most efficient for writing/reading to a file
(BTW- what is struct alignment?)
- preparing data for reading and writing
- managing data that isn't saved yet
- implementing an "Undo" scheme
I have lots of source code to look at, but references to any develop or MacTech
articles on the subject would be greatly appreciated. Is any of this in
the Inside Mac volumes? I have been browsing the Files volume without
finding anything that looks like it answers my questions.
Any help appreciated
Vincent P Salupo
Eli Lilly and Company
v.salupo@lilly.com
As usual: All opinions are mine and do not reflect the views of my
Company, Managers, co-workers, spouse, children, dog
etc....
+++++++++++++++++++++++++++
>From woody@alumni.caltech.edu (William Edward Woody)
Date: 27 Mar 1996 01:53:20 GMT
Organization: In Phase Consulting
v.salupo@lilly.com (Vince Salupo) wrote:
> Most Mac programming books deal with interface issues. I haven't run across a
> clear explanation of how to do any of the following in C:
>
> - create structures that are most efficient for writing/reading to a file
The Macintosh is happiest reading and writing large blocks of data to
and from a file. If you are storing your file as a series of structures,
and you are writing those structures directly to disk (using FSRead/FSWrite),
then just about any alignment is going to be relatively inefficient.
It's a tradeoff here--do you want the fastest read/write time possible?
Or do you want a simle solution which is fast enough and easy to maintain?
I'd suggest the latter.
> (BTW- what is struct alignment?)
The elements in a structure are aligned to certain rules in order to
maintain efficient access to the elements of those structures. This
alignment is done by padding your structures with empty space, according
to some simple rules, depending on the alignment.
The most common alignment is the 68K 2-byte alignment rules. These
rules were first developed because the 68000 processor is unable to
read 2-byte or 4-byte data objects which are aligned on an odd byte.
Compilers align this data by padding the data to make shorts and longs
land on even byte boundaries.
Thus, a structure:
struct {
char byte1;
short word1;
char byte2;
short word2;
} s;
would be aligned:
offset data
0 byte byte1
1 byte (padding)
2 word word1
4 byte byte2
5 byte (padding)
6 word word2
Notice that two bytes of padding are added, one after 'byte1' and one
after 'byte2'; this causes the data that follows to be word-aligned.
Now if arranged the structure to be:
struct {
char byte1;
char byte2;
short word1;
short word2;
};
then our alignments are:
offset data
0 byte byte1
1 byte byte2
2 word word1
4 word word2
Notice that as the byte sized objects do not have to be word aligned
(only 2 and 4 byte, and larger, objects), the byte sized object 'byte2'
can be placed at offset 1.
This has the side effect that the structure is two bytes smaller, by the
way.
Different rules exist; there is a 4-byte alignment (where objects are
aligned to 4 byte boundaries instead of two byte boundaries), and PowerPC
alignment (where objects are aligned to be on the boundary that reflects
the object's size), but I am not really sure how they work.
> - preparing data for reading and writing
It depends on the internal structures you are using for your application.
As a general rule, I tend to simply write out a copy of my internal
data structures in a format which makes it easy to reconstruct my
internal data structures from the file.
I do this by first writing a header to the file which is a structure
which contains the version number of this file. (Just in case I change
my internal structures, and hense the format of the file.)
Then I walk my different data structures, writing out my structures,
along with some information as to what that structure is.
One method I sometimes use is to write out 'tags'; each 'tag' is a
simple structure:
struct {
short type;
long offset;
};
where 'type' is an integer which I assign to my different internal
structures, and 'offset' is the offset to the next tag in the file.
This has several advantages. First, you can skip types which you don't
understand, allowing you to add information to later versions of the file
which can be read by earlier versions of your program.
Second, you can nest tags; the offset in each nesting would point to the
next associated tags, but the data that follows can also contain tags.
Third, if you assign version information to your tags (such as the number
of bytes you think you need to write out your structure), you can add
new fields to the end of your structure. Then, when you read the data
in, if the data following the tag is larger than your structure, simply
ignore it. This also allows later versions of your software to be able
to write files readable by earlier versions of your software.
> - managing data that isn't saved yet
That's easy--at every entry point which can modify your data, call a function
which flips a 'dirty' bit. This 'dirty' bit then indicates if your data
needs to be saved; this allows you to take the appropriate action where
needed.
> - implementing an "Undo" scheme
Undo is difficult.
There are three schemes for doing 'Undo' which I know about.
The first scheme is good for small databases--simply preserve a copy of
the unedited database along with the edited version. Then, when the
user requests the 'undo' function, swap the databases.
For example, suppose you are able to store all of your database in a
single Macintosh handle. Then, when an editing procedure takes place,
you do the following steps:
1) Update the dirty flag.
2) Delete the old 'undo' handle.
3) Make a copy of your database handle and store it in the undo
handle holder.
4) Modify your database.
When you undo, then swap the current with the undo database.
The second scheme is a bit more difficult, but uses far less memory.
It works well with drawing programs, but can also be made to work with
a text editor.
When an edit takes place, you create a record which stores the actions
that are taken to perform that edit. For example, suppose you draw a new
line. Then your edit record contains the 'add line' command, and the
coordinates of that line.
Then, you keep the last edit record in your 'undo' pointer. This allows
you to know what you changed the last time the user edited the file.
Then, when it comes time to undo the file, you can look at the 'last
edit' record, and reverse it's actions.
You can extend this idea to multiple undos and multiple redos; just
keep the last 10 or 20-odd edit records.
The third scheme is a variant of the second. It involves applying the
editing records on the fly to the database to represent the final
editing product.
Assume you have a routine, call it 'GetCurrentState'. This routine
would normally return your database so you can display it and the
like. Instead of preserving your 'edit' states to the database,
and keeping around the changed database, you instead keep around
the _unchanged_ database, and have your 'GetCurrentState' apply
the edits to the database on the fly.
This works very well for thinks like drawing programs: if you have a
routine, 'GetNumberOfObjects' which returns the number of lines, circles,
and the like, then this routine would be modified to look through
the list of edit records, counting the number of objects that were
inserted or deleted, to find the final number of objects to display.
Another routine, 'GetObjectByIndex' would return the appropriate
object, either from the edit record, or from the orignal database,
of the line, circle, or other object to process.
This has the advantage that if you can optimize the database access
routines (like in a drawing program), your editing and undo process
becomes simple--simply add a new edit record to the list of edit
records. Undoing is removing the last edit, and updating the display.
> Any help appreciated
I hope this helps.
- Bill
--
William Edward Woody | e-mail: woody@alumni.cco.caltech.edu
In Phase Consulting | WWW: http://www.alumni.caltech.edu/~woody
337 W. California #4 | Fax: (818) 502-1467
Glendale, CA 91203 | ICBM: N:34.15' W:118.25'
+++++++++++++++++++++++++++
>From jumplong@aol.com (Jump Long)
Date: 27 Mar 1996 02:05:34 -0500
Organization: America Online, Inc. (1-800-827-6364)
>Most Mac programming books deal with interface issues. I haven't
>run across a clear explanation of how to do any of the following
>in C:
>
>- create structures that are most efficient for writing/reading
>to a file
> (BTW- what is struct alignment?)
>
>- preparing data for reading and writing
>
>- managing data that isn't saved yet
>
>- implementing an "Undo" scheme
>
>I have lots of source code to look at, but references to any
>develop or MacTech articles on the subject would be greatly
>appreciated. Is any of this in the Inside Mac volumes? I have
>been browsing the Files volume without finding anything that
>looks like it answers my questions.
Some of the advice you're looking for can be found in a Technical Note I
wrote "FL16 - File Manager Performance and Caching"
<http://dev.info.apple.com/technotes/Archive/Files/fl_16.html>
- Jim Luther
---------------------------
>From nordic@inetnebr.com (Dave)
Subject: How to Do Registration Codes
Date: Thu, 14 Mar 1996 13:47:05 -0600
Organization: Internet Nebraska
Does anyone have any pointers on how to program registration codes? I
know how to do the dialogs and all of the general programming. My
question is how to set up a system where specific codes will unlock the
program.
Thanks
Dave
============================================================================
Nordic Software Inc. - dedicated to educational software since 1986
P.O. Box 6007 Phone: (402) 488 - 5086
Lincoln, NE 68506 Fax: (402) 488 - 2914
- ---------------------------------------------
E-Mail info@nordicsoftware.com
Free educational software drawing on our web page each week!
http://www.nordicsoftware.com/
============================================================================
+++++++++++++++++++++++++++
>From jim@bogie2.bio.purdue.edu (Jim Cavera)
Date: Thu, 14 Mar 1996 18:37:35 -0500
Organization: Purdue University
> Does anyone have any pointers on how to program registration codes? I
> know how to do the dialogs and all of the general programming. My
> question is how to set up a system where specific codes will unlock the
> program.
My personal method:
The resource fork of your program will contain a you-defined resource
that consists of a single stream of characters, say 10-long like this:
fz93e1n43a
Your program looks for this on start-up. If it's missing, ExitToShell().
The user must enter they're registration code, also 10-digits like this:
36fizamc9q
This also gets files away in a different resource in the prefs file. If
the first resource is present, but the second one is missing, prompt the
user to enter they're registration code. You get the idea.
Now then, when your app starts up, it fetches the code from its res fork
and the user's registration code from the prefs file. It adds them
together on a character by character basis. It then subtracts a constant
from each character. It then compares the character array (c-string)
that remains to a caracter array in the code. If there are differences,
it exits. Thus you have :
fz93e1n43a
+ 36fizamc9q
-----------------
********** <---- some character garbage
- nnnnnnnnnn <---- any arbitrary constant
-----------------
thissucks! <---- a string to compare with the internal one
This method works well as you don't have to re-compile anything to give
each copy a unique identifier. Though it's not ultra-secure by any stretch,
it seems to work very well. Comments from the net?
- Jim Cavera (bit-pushing slave)
jim@bogie2.bio.purdue.edu
BTW: I don't know how the "pros" do it -- this is just something I
dreamed up on my own. Take it with a mine of salt.
+++++++++++++++++++++++++++
>From flisakow@fontina.cs.wisc.edu (Shaun Flisakowski)
Date: 15 Mar 1996 08:11:22 GMT
Organization: U of Wisconsin CS Dept
In article <jim-1403961837350001@ibcrc3.bio.purdue.edu>,
Jim Cavera <jim@bogie2.bio.purdue.edu> wrote:
>> Does anyone have any pointers on how to program registration codes? I
>> know how to do the dialogs and all of the general programming. My
>> question is how to set up a system where specific codes will unlock the
>> program.
>
>My personal method:
>
[snip]
>
> fz93e1n43a
> + 36fizamc9q
> -----------------
> ********** <---- some character garbage
> - nnnnnnnnnn <---- any arbitrary constant
> -----------------
> thissucks! <---- a string to compare with the internal one
I agree with the basic concept, but have a few things to add.
You should not use literal strings in the code. These are very
easy for a cracker to locate. Converting the strings to numbers,
then using them is a much better plan.
You should keep in mind that you don't want anything that can be
easily "observed" via a debugger. If the password string entered
is decimated and scattered about, you're making life that much
harder for a cracker.
This is one place where modularity should be avoided, as well.
The check can be spread out over many functions (place a comment
by each part in your source to help you find them).
This expands the area that must be disassembled/examined.
If you can intertwine your registration check with another part
of the software, all the better. If the software is partially
broken by being cracked, you have succeeded.
You might want to try cracking a product; if you're sucessful,
ask yourself what the programmer could have done to make it more
difficult.
--
Shaun flisakow@cs.wisc.edu
"In your heart you know its flat."
-Flat Earth Society
+++++++++++++++++++++++++++
>From gumboot@airdmhor.gen.nz (Simon Hosie)
Date: 17 Mar 1996 00:58:24 +1300
Organization: Airdmhor : a couple of BBS's, a bunch of people, and a cat.
Shaun Flisakowski:
> If you can intertwine your registration check with another part
> of the software, all the better. If the software is partially
> broken by being cracked, you have succeeded.
> You might want to try cracking a product; if you're sucessful,
> ask yourself what the programmer could have done to make it more
> difficult.
The problem is that all the really good methods for keeping people out of
your code are completely system unfriendly..
The best thing I can think of is to interpret your own instruction set
which is decoded by the interpreter using a seed you give it as a
registration number of some sort.. The problem there is getting that number
to be different from machine to machine - otherwise one person can register
their copy and that of everyone they know..
+++++++++++++++++++++++++++
>From avg@xs4all.nl (Arno van Goch)
Date: Sat, 16 Mar 1996 15:02:23 GMT
Organization: XS4ALL, networking for the masses
nordic@inetnebr.com (Dave) wrote:
>Does anyone have any pointers on how to program registration codes? I
>know how to do the dialogs and all of the general programming. My
>question is how to set up a system where specific codes will unlock the
>program.
You should make registration codes that hold all the information you
want *plus* a checksum. The checksum is important because it makes
sure that not any random code is accepted as a valid registration
code.
An older version of a well known commercial program had codes like
56242363-31
Where '56242363' was the serial number, and '31' the sum of all the
numbers that make up the serial number.
So a code 56242363-32 would not be accepted.
To disguise the algorithm better codes could be written as 5624236331
(leaving away the '-' ). Or mangle those numbers in a specific way
like 3235614236.
In a program of mine I wanted registration in the following form.
Registration name : ...
Registration code : ...
The registration code should only work with a valid registration name.
This makes it clear for the registered users that they can give their
codes away to friends, but not without leaving their name in the
pirated version.
The registration code should therefore hold the following information
:
-Serial number
-Checksum of registration name
-Checksum of the registration code
I decided how many bits I wanted to use for each. Checksums were
mostly done with XOR operations. The checksum of the registration code
was calculated something like (Serialnumber) XOR (Name checksum) XOR
(constant). The constant is a fixed value that indicates the
application. I could therefore use the same algorithm for a different
program by just changing this constant.
As a bones all the resulting bits were mangled and converted to an
'ASCII' notation.
Other things to consider :
-A not-too-strict calculation of the name-checksum. Allow some typos
and make it case insensitive
-While Converting from bits->ASCII try to avoid characters that could
cause mistakes like 0 or O, 1 of l.
-- Arno van Goch --
+++++++++++++++++++++++++++
>From Larry Hotchkiss <wcdc@winternet.com>
Date: Sat, 16 Mar 1996 12:23:27 -0600
Organization: StarNet Communications, Inc
Simon Hosie wrote:
>
> Shaun Flisakowski:
> > If you can intertwine your registration check with another part
> > of the software, all the better. If the software is partially
> > broken by being cracked, you have succeeded.
>
> > You might want to try cracking a product; if you're sucessful,
> > ask yourself what the programmer could have done to make it more
> > difficult.
>
> The problem is that all the really good methods for keeping people out of
> your code are completely system unfriendly..
>
> The best thing I can think of is to interpret your own instruction set
> which is decoded by the interpreter using a seed you give it as a
> registration number of some sort.. The problem there is getting that number
> to be different from machine to machine - otherwise one person can register
> their copy and that of everyone they know..
How about using the volume serial number off their hard drive.
The only problem I see hear is if thier system craches and they get a new
drive they will need to get a new code to use it.
--
Larry H.
+++++++++++++++++++++++++++
>From haverber@winternet.com (Bill Haverberg)
Date: Sun, 17 Mar 1996 06:23:40 GMT
Organization: StarNet Communications, Inc
Larry Hotchkiss <wcdc@winternet.com> wrote:
> How about using the volume serial number off their hard drive.
>The only problem I see hear is if thier system craches and they get a new
>drive they will need to get a new code to use it.
>--
I saw in the major access programming group that someone was offering
a free security dll that works with the volume serial number. My
system crashed and I lost track of it before I could get ahold of it,
but a polite request on the group should flush it out.
+++++++++++++++++++++++++++
>From Janet <dascalu@math.tau.ac.il>
Date: Tue, 19 Mar 96 19:44:58
Organization: NetVision LTD.
In Article<314B071F.1219@winternet.com>, <wcdc@winternet.com> writes:
>
> Simon Hosie wrote:
> >
> > Shaun Flisakowski:
> > > If you can intertwine your registration check with another part
> > > of the software, all the better. If the software is partially
> > > broken by being cracked, you have succeeded.
> >
> > > You might want to try cracking a product; if you're sucessful,
> > > ask yourself what the programmer could have done to make it more
> > > difficult.
> >
> > The problem is that all the really good methods for keeping people out
of
> > your code are completely system unfriendly..
> >
> > The best thing I can think of is to interpret your own instruction set
> > which is decoded by the interpreter using a seed you give it as a
> > registration number of some sort.. The problem there is getting that
number
> > to be different from machine to machine - otherwise one person can
register
> > their copy and that of everyone they know..
>
>
> How about using the volume serial number off their hard drive.
> The only problem I see hear is if thier system craches and they get a new
> drive they will need to get a new code to use it.
> --
>
>
why mess with this al all, do something simple, even if
someone broke your protection and it is distrebuted like this, change the
method to something else on the next version, if someone
doesn't want to pay for shareware HE WILLL NOT DO IT
+++++++++++++++++++++++++++
>From hsoi@tamu.edu (John C. Daub)
Date: 20 Mar 1996 04:57:48 GMT
Organization: Wish I Had More Of It
all of the registration methods here seem pretty good, but very complex.
i guess what to use to decide what choice to take would be just what
you were wanting in the end. if a high security mechanism, maybe try
that robust 2 string-add-subtract-thissucks method (with the suggestions
that other guy gave to it). but it's true, that could still be something
"traced" in workings via Macsbug (and other things) and if they see what
you're doing, you're sol.
but then, aside from PGP, what can't be cracked? :)
i thought of a simple technique the other day, and i wonder what people
think about it. sure, it's NOT very robust, nor secure, but i'm more
interested in something that could be used to keep the majority of
the public (of shareware users) from features until they register. like
if i had a demo version, the "serial number they obtain upon paying their
shareware fee" would totally unlock the program.
it's very simple...
create a pattern for your registration number. like so many "characters"
(the more the merrier). let's say we'll have 15 characters.
now, they could be anything, numbers, letters, maybe even other things
like !@#$%^&^&* or something :)
now, lay out a pattern (sorta like an FMAT in concept, on Macs). oh, i just
realized this was cross posted to alt.comp.shareware.programmer, so sorry
for the mac references, but the concept can remain.
something like, 3 digits, hyphen, 2 digits, 2 letters, 2 digits hypen,
digit, letter, 2 digits.
so like: 123-45-AB67-8C90
then, you can check for this pattern in your registration dialog code.
get the string from the reg dialog, parse it byte by byte. you can even
do another first check, if not "15" characaters long, reject it...if
it is 15, parse for the "type" of character...like for the first character,
if it's not a digit, reject.
and then you could do even more...say the third character had to be a digit
between 5 and 9 but not 6. or 1 or 4 or 8 only. or always R or something.
that could help to even make it more complex to get around.
and, if you use the reg code to keep track of things (like they're customer
number 50 to register, the type of computer they have, or whatever other
database/recordkeeping you might want to use), you could have your own
sort of "code" for all this built in there, y'know? just gotta use the
imagination :)
and of course, the more cryptic you can make it to your user, probably
the better it is secruity wise.
of course, anyone with time and effort would eventually get through almost
anything, but perhaps this is a way to do it all "interally" without
resources or something.
oh, and a way to know if they've registered or not...upon startup, it's
doubtful they'd have a prefs file. don't create one until after a successful
registration...or, have something in the prefs file (again, cryptic) to
note they've not registered yet. again, not high security, but a fast,
cheap, easy method, IMHO.
any comments?
--
John C. Daub (aka Hsoi) | <mailto:hsoi@tamu.edu>
Grad Student, Lab Manager | <http://http.tamu.edu:8000/~jcd7106/>
Self-proclaimed Mac Guru | Department of Speech Communication
Will program for food. | Texas A&M University, USA
"Ain't it funny how that money rots your brain?" -COC
+++++++++++++++++++++++++++
>From troika@panix.com (Mark Coniglio)
Date: Thu, 21 Mar 1996 08:56:38 -0500
Organization: Troika Ranch
In article <hsoi-1903962303090001@ppp16-17.rns.tamu.edu>, hsoi@tamu.edu
(John C. Daub) wrote:
> something like, 3 digits, hyphen, 2 digits, 2 letters, 2 digits hypen,
> digit, letter, 2 digits.
>
> so like: 123-45-AB67-8C90
>
> then, you can check for this pattern in your registration dialog code.
>
> get the string from the reg dialog, parse it byte by byte. you can even
> do another first check, if not "15" characaters long, reject it...if
> it is 15, parse for the "type" of character...like for the first character,
> if it's not a digit, reject.
>
> and then you could do even more...say the third character had to be a digit
> between 5 and 9 but not 6. or 1 or 4 or 8 only. or always R or something.
>
> that could help to even make it more complex to get around.
>
> and, if you use the reg code to keep track of things (like they're customer
> number 50 to register, the type of computer they have, or whatever other
> database/recordkeeping you might want to use), you could have your own
> sort of "code" for all this built in there, y'know? just gotta use the
> imagination :)
>
Your method is good. Another scheme, to make the code somewhat harder to
figure out, is to say create a "hash" code from the last four digits, and
then make sure that this value matches a predefined value. For instance,
if we call the last four digits A, B, C and D, you might take the result
of (((A*B)+C*100)/D) % 10. Then pick a number that marks a valid serial
number. Let's say that it is 8. For 9632 or 5594 the result is 8. But
other numbers don't work.
Try it.
Mark Coniglio
--
mail: troika@panix.com
http: www.art.net/Studios/Performance/Dance/Troika_Ranch/TroikaHome.html
+++++++++++++++++++++++++++
>From f-reed@primenet.com (Frank Reed)
Date: 22 Mar 1996 16:38:01 -0700
Organization: Primenet
nordic@inetnebr.com (Dave) wrote:
>Does anyone have any pointers on how to program registration codes? I
>know how to do the dialogs and all of the general programming. My
>question is how to set up a system where specific codes will unlock the
>program.
I've been following this string with interest because I have a similar
question, but I'm not sure I understand the big picture. Perhaps
someone would be kind enough to tell me if the following scenario is
substantially correct.
1. A user downloads a shareware program to try it out. To give users
an incentive to register, the registered version of the program
behaves better in some respect than the shareware version.
2. The user decides to register the program. To do so, he sends
money or a credit card number to the vendor along with (and this is
the part I'm not sure about) some kind of unique information about
himself or his system, such as his registration name or a code
generated by the shareware version, perhaps derived from a hard disk
serial number or BIOS ROM version number.
3. The shareware vendor receives the unique information from the
purchaser, and from it generates an unlock code, which is sent to the
purchaser.
4. The purchaser enters the unlock code into a registration dialog in
the shareware product. The shareware combines the unique information
referenced above with the unlock code and determines whether the
unlock code is valid. If so, the registered version functionality of
the product is enabled.
Is that pretty much the way it works?
- Frank Reed
+++++++++++++++++++++++++++
>From flisakow@fontina.cs.wisc.edu (Shaun Flisakowski)
Date: 23 Mar 1996 06:56:35 GMT
Organization: U of Wisconsin CS Dept
In article <4ivdkp$7r0@nnrp1.news.primenet.com>,
Frank Reed <f-reed@primenet.com> wrote:
>nordic@inetnebr.com (Dave) wrote:
>
>>Does anyone have any pointers on how to program registration codes? I
>>know how to do the dialogs and all of the general programming. My
>>question is how to set up a system where specific codes will unlock the
>>program.
>
>I've been following this string with interest because I have a similar
>question, but I'm not sure I understand the big picture. Perhaps
>someone would be kind enough to tell me if the following scenario is
>substantially correct.
Yes, you seem to be dead on.
>1. A user downloads a shareware program to try it out. To give users
[snip]
>
>2. The user decides to register the program. To do so, he sends
>money or a credit card number to the vendor along with (and this is
>the part I'm not sure about) some kind of unique information about
>himself or his system, such as his registration name or a code
>generated by the shareware version, perhaps derived from a hard disk
>serial number or BIOS ROM version number.
[snip]
This is the a difficult part, ideally you would like to obtain
some number that is unique for each machine, and not going to
change if the user reinstalls the OS, obtains new hardware, or
gets a divorce.
--
Shaun flisakow@cs.wisc.edu
"In your heart you know its flat."
-Flat Earth Society
+++++++++++++++++++++++++++
>From weare@galaxy.ucr.edu (christopher weare)
Date: 23 Mar 1996 00:05:00 -0800
Organization: University of California, Riverside
In article <4ivdkp$7r0@nnrp1.news.primenet.com>,
Frank Reed <f-reed@primenet.com> wrote:
>2. The user decides to register the program. To do so, he sends
>money or a credit card number to the vendor along with (and this is
>the part I'm not sure about) some kind of unique information about
>himself or his system, such as his registration name or a code
>generated by the shareware version, perhaps derived from a hard disk
>serial number or BIOS ROM version number.
>
Actually, no unique information is needed. The reg code is usualy a long
string that has billions or trillions of possible combinations. However,
only a small subset of those combinations (determined by some algorithm
used by the vendor) is actually valid. When the user gets the code,
they type it in and the program simply determines if the code belongs to the
small subset of valid codes.
-chris
+++++++++++++++++++++++++++
>From wjohn@webcom.com (Wolfgang John)
Date: Sat, 23 Mar 1996 16:03:36 GMT
Organization: Call America Internet Services +1 (805) 541 6316
troika@panix.com (Mark Coniglio) wrote:
>In article <hsoi-1903962303090001@ppp16-17.rns.tamu.edu>, hsoi@tamu.edu
>(John C. Daub) wrote:
>> something like, 3 digits, hyphen, 2 digits, 2 letters, 2 digits hypen,
>> digit, letter, 2 digits.
>>
>> so like: 123-45-AB67-8C90
>>
>> then, you can check for this pattern in your registration dialog code.
>>
>> get the string from the reg dialog, parse it byte by byte. you can even
>> do another first check, if not "15" characaters long, reject it...if
>> it is 15, parse for the "type" of character...like for the first character,
>> if it's not a digit, reject.
>>
>> and then you could do even more...say the third character had to be a digit
>> between 5 and 9 but not 6. or 1 or 4 or 8 only. or always R or something.
>>
>> that could help to even make it more complex to get around.
>>
>> and, if you use the reg code to keep track of things (like they're customer
>> number 50 to register, the type of computer they have, or whatever other
>> database/recordkeeping you might want to use), you could have your own
>> sort of "code" for all this built in there, y'know? just gotta use the
>> imagination :)
>>
>Your method is good. Another scheme, to make the code somewhat harder to
>figure out, is to say create a "hash" code from the last four digits, and
>then make sure that this value matches a predefined value. For instance,
>if we call the last four digits A, B, C and D, you might take the result
>of (((A*B)+C*100)/D) % 10. Then pick a number that marks a valid serial
>number. Let's say that it is 8. For 9632 or 5594 the result is 8. But
>other numbers don't work.
I often wonder whether "figuring out" a registration code is the
problem, or is it people passing around the number once they have
obtained it by registering or other means?
--
Wolfgang John - Shareware -
wjohn@webcom.com http://www.webcom.com/wjohn
- Phone Dialer and Logger - CD Player and Library - Win3.1 / Win95
+++++++++++++++++++++++++++
>From Brandon Staggs <bstaggs@aloha.net>
Date: Sat, 23 Mar 1996 09:56:06 -1000
Organization: Psalm 138:2 KJV
Frank Reed wrote:
> 2. The user decides to register the program. To do so, he sends
> money or a credit card number to the vendor along with (and this is
> the part I'm not sure about) some kind of unique information about
> himself or his system, such as his registration name or a code
> generated by the shareware version, perhaps derived from a hard disk
> serial number or BIOS ROM version number.
This is one way, but people doing it this was forget that people like to
upgrade their computer systems. Suppose you register program X on your
386 and give them your BIOS number or HD format number or whatever. So
you love the program, but when you finally get your Super Pentium Pro
Plus Gold, 500mhz of course, lo and behold you have a different BIOS
number so your favorite program wont work on your new wonder machine. So
you have to go back to the vendor (assuming he still is around) and get
a new code. What a waste of time and a hassle.
The program I am currently devoloping uses the person's NAME as the
"unique identifier" and just matches up a name with a reg code. Of
course he could give it to his friends--but at least if I run into it on
the net I know who leaked. You always trade off convienience for a
chance your program will be pirated more. To me it seems like such a
waste of time to get into this full blown BIOS stuff and a hassle for
the user. If someone wants to pirate your program they will--any hacker
can jump over copy-protection code. You can find a crack for just about
any program out there anyway.
My program will be coded in such a way that there is nothing I need to
send a user when they register excpet for their registration code. Since
I don't believe in writing crippleware all I have is one measly nag box
that also happens to double as the registration code dialog. Once they
put in the reg code it turns of the nag and gets them free updates until
I decide to change the registration code scheme when I want more money
for the upgrade. No disks to mail or anything. Of course I can charge
more if they want everything on disk.
Happy registrations!
_____________________________________________________________________
Brandon L. Staggs Psalm 138:2 KJV bstaggs@aloha.net
Home Page: http://www.aloha.net/~bstaggs/index.html
King James Bible Page: http://www.aloha.net/~bstaggs/kjb.html
Commodore 64 Memories: http://www.aloha.net/~bstaggs/c64.html
+++++++++++++++++++++++++++
>From Steve@emer.com (Steve Wilson)
Date: 23 Mar 1996 20:14:43 GMT
Organization: Emergent Behavior
In article <4j07b3$n2q@spool.cs.wisc.edu>, flisakow@fontina.cs.wisc.edu
(Shaun Flisakowski) wrote:
> This is the a difficult part, ideally you would like to obtain
> some number that is unique for each machine, and not going to
> change if the user reinstalls the OS, obtains new hardware, or
> gets a divorce.
You can use the creation date for the boot volume of the machine. That
can be changed, but you have to reformat your HD.
Steve Wilson
Emergent Behavior
(415) 494-6763
Steve@emer.com
+++++++++++++++++++++++++++
>From flisakow@fontina.cs.wisc.edu (Shaun Flisakowski)
Date: 24 Mar 1996 02:54:56 GMT
Organization: U of Wisconsin CS Dept
In article <4j0bbc$f3v@galaxy.ucr.edu>,
christopher weare <weare@galaxy.ucr.edu> wrote:
>In article <4ivdkp$7r0@nnrp1.news.primenet.com>,
>Frank Reed <f-reed@primenet.com> wrote:
>>the part I'm not sure about) some kind of unique information about
>>himself or his system, such as his registration name or a code
>>generated by the shareware version, perhaps derived from a hard disk
>>serial number or BIOS ROM version number.
>Actually, no unique information is needed. The reg code is usualy a long
>string that has billions or trillions of possible combinations. However,
>only a small subset of those combinations (determined by some algorithm
>used by the vendor) is actually valid. When the user gets the code,
>they type it in and the program simply determines if the code belongs to the
>small subset of valid codes.
Oh course, then you just gave that person a "global" key to your
product, which they are then free to give to all their friends,
post onto the Net, or whatever else they like.
That certainly would make life easy for pirates, you have eliminated
the need to figure out how a valid code is created.
--
Shaun flisakow@cs.wisc.edu
"In your heart you know its flat."
-Flat Earth Society
+++++++++++++++++++++++++++
>From gumboot@airdmhor.gen.nz (Simon Hosie)
Date: 25 Mar 1996 01:38:03 +1200
Organization: Airdmhor : a couple of BBS's, a bunch of people, and a cat.
Frank Reed:
> 2. The user decides to register the program. To do so, he sends
> money or a credit card number to the vendor along with (and this is
> the part I'm not sure about) some kind of unique information about
> himself or his system, such as his registration name or a code
> generated by the shareware version, perhaps derived from a hard disk
> serial number or BIOS ROM version number.
Of course.. encode their credit card number (the number that gets the
money out, I mean) into the registered program - what pillock is going to
start handing that around? Better yet, make part of the registration fee a
photo of them in some form of compromising position so that that can be
scanned and linked into the registered version in an easily extractable way.
+++++++++++++++++++++++++++
>From dickmac@ix.netcom.com (Richard MacDonald)
Date: Sun, 24 Mar 1996 18:13:12 -0700
Organization: Netcom
On 25 Mar 1996 01:38:03 +1200, gumboot@airdmhor.gen.nz (Simon Hosie) wrote:
>
> Of course.. encode their credit card number (the number that gets the
>money out, I mean) into the registered program - what pillock is going to
>start handing that around? Better yet, make part of the registration fee a
>photo of them in some form of compromising position so that that can be
>scanned and linked into the registered version in an easily extractable way.
I believe that it is sufficient to use the licensee's name and company name
(with city, state if there is no company) to generate the code, then display
that information prominently on the main screen or window whenever the program
is run. By encrypting the name and company inside the .EXE file you can prevent
it from changing. That way if a licensee gives it to someone else it will still
display his or her name and company when that person uses it. Then all you need
is someone to report it...
Dick MacDonald
+++++++++++++++++++++++++++
>From steve@tropheus.demon.co.uk (Stephen Wolstenholme)
Date: Mon, 25 Mar 1996 19:10:03 GMT
Organization: (none)
On 22 Mar 1996 16:38:01 -0700, f-reed@primenet.com (Frank Reed) wrote:
>2. The user decides to register the program. To do so, he sends
>money or a credit card number to the vendor along with (and this is
>the part I'm not sure about) some kind of unique information about
>himself or his system, such as his registration name or a code
>generated by the shareware version, perhaps derived from a hard disk
>serial number or BIOS ROM version number.
>
>3. The shareware vendor receives the unique information from the
>purchaser, and from it generates an unlock code, which is sent to the
>purchaser.
>
>4. The purchaser enters the unlock code into a registration dialog in
>the shareware product. The shareware combines the unique information
>referenced above with the unlock code and determines whether the
>unlock code is valid. If so, the registered version functionality of
>the product is enabled.
That's more or less what I do. I use the persons name (or company
name) to generate a registration number. The number and name
combination stops the application countdown or enables any facilities
that have been inhibited by the countdown. I don't think it's a very
good idea to generate a registration number based on something that is
unique to the system - the software license is owned by the
person/company not the chunk of hardware that it is running on.
Steve
- ------------------------------------------------------------------------
Stephen Wolstenholme, Cheadle Hulme, Cheshire, UK
steve@tropheus.demon.co.uk
Author of Neural Planner, Windows 3.1x neural network system
http://www.xmission.com/~wintrnx/regnet/86p.htm
ftp.demon.co.uk/pub/ibmpc/win3/apps/ai/np400.zip
ftp.coast.net/SimTel/win3/neurlnet/np400.zip
- ------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From Jan.Hertsens@ping.be (Jan Hertsens)
Date: Tue, 26 Mar 1996 18:02:10 GMT
Organization: A Forest Software
Steve@emer.com (Steve Wilson) wrote:
>
>You can use the creation date for the boot volume of the machine. That
>can be changed, but you have to reformat your HD.
Or spend 3 minutes writing a program that can read and write this part
of the bootsector....
(Just a thought)
--
Greetz, _ o PGP: D7 60 17 56 37 85 B3 69 5A 37 8F EE C5 6A BE 57
| _ _.._ |<)_/# <<< Don't get mad. Get EVEN. Get CheatMachine! >>>
\_|(/_(_|| | TT <T http://www.SliceOfLife.com/Official/AFOREST/CM.HTM
+++++++++++++++++++++++++++
>From robin@perth.DIALix.oz.au (Robin Kay)
Date: 27 Mar 1996 09:35:32 +0800
Organization: DIALix Services, Perth, Australia.
Using the Chip ID or Disk drive for registration will be okay if you keep
track of who has registered. Then if they upgrade their machine, you can
give them a new registration number for free. You will soon know if
someone is abusing the system: you wouldn't believe them if they upgraded
five times in the first month, or "upgraded" from a Pentium to a 486.
At most someone might get away with one free registration for a friend.
+++++++++++++++++++++++++++
>From innovative_technologies@actcom.co.il (innovative technologies)
Date: Wed, 27 Mar 1996 01:53:33 GMT
Organization: innovative technologies
>That's more or less what I do. I use the persons name (or company
>name) to generate a registration number. The number and name
>combination stops the application countdown or enables any facilities
>that have been inhibited by the countdown. I don't think it's a very
>good idea to generate a registration number based on something that is
>unique to the system - the software license is owned by the
>person/company not the chunk of hardware that it is running on.
>Steve
Hi Steve,
How do you handle than SITE licences? Or passing around the S/W
between friends (especially if your market has limited size)?
Why not offer any user immidiate new registration if he buys a new
computer and just sends the receipt?
best regards,
Innovative Technologies
Telecom, Multimedia and VoiceMail products
and home of the TYIN adavanced utilities.
email: innovative_technologies@actcom.co.il
Check our WEB site at:
WWW: http://www.israel.net/innovative/
(note: When responding, please send email in addition to post here).
+++++++++++++++++++++++++++
>From "Andrew C. Plotkin" <erkyrath+@CMU.EDU>
Date: Wed, 27 Mar 1996 01:36:24 -0500
Organization: Senior, Math/Computer Science, Carnegie Mellon, Pittsburgh, PA
innovative_technologies@actcom.co.il (innovative technologies) writes:
> >That's more or less what I do. I use the persons name (or company
> >name) to generate a registration number.
I find this method relatively unannoying (speaking as a user.)
> How do you handle than SITE licences? Or passing around the S/W
> between friends (especially if your market has limited size)?
Actually, limited size works the other way. The shareware game I put
out uses an even weaker scheme; a fixed password. If the players xerox
the code sheet, they beat the scheme. Somehow, I still make money. I
once saw a binary patch to bypass the password check on my game, and I
*still* make money. Why? I wrote a good puzzle-game. People like it.
They'd rather pay me than cheat me.
> Why not offer any user immidiate new registration if he buys a new
> computer and just sends the receipt?
I'm going to run off a dozen copies of my receipt and mail them to a
dozen different shareware companies? Yeah, right. Way too much work.
Maybe you think that's a lazy attitude, but I'm buying a new computer
soon, and I don't believe I have *any* shareware programs that I'll
have to write to the author for a new password. I'll have to spend
some time retyping the passwords I've gotten in the past three years,
but they're all in a folder right next to me.
So my lazy attitude works.
--Z
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
+++++++++++++++++++++++++++
>From andrewwelc@aol.com (AndrewWelc)
Date: 27 Mar 1996 05:25:48 -0500
Organization: America Online, Inc. (1-800-827-6364)
> I find this method relatively unannoying (speaking as a user.)
Agreed. The system we use generates a license code based on a product
name, licensee name and the number of copies they license. If the program
is given to a friend, it is automagically unregistered.
The license codes are all letters (case doesn't matter), which is
important from a usability point of view for users.
Any programmer/hack can easily bypass any system you invent, it really
shouldn't be much of an issue when designing a registration system IMHO.
The trickier you get, the more time you waste on it rather than your
program, and the more of a fun mental exercise you give to folks with the
expertise.
Heck, come up with a funky, tricky scheme and then challenge us to break
it. :)
+--------------------------------------------------------------+
| Andrew Welch - Thaumaturgist - Ambrosia Software, Inc. |
+-------------------------------+------------------------------+
| AOL-> Keyword: Ambrosia | eWorld-> Shortcut: Ambrosia |
| CIS-> GO word: Ambrosia | http://www.AmbrosiaSW.com/ |
+-------------------------------+------------------------------+
---------------------------
>From grs124@psu.edu (Greg Simon)
Subject: How to find CTB devices ?
Date: Mon, 25 Mar 1996 10:28:30 -0500
Organization: Penn State University
What's the proper way to find out what CTB devices (e.g., "Modem Port",
etc) are available on a machine?
or, is "Inside the Macintosh Communications Toolbox" online anywhere?
Thanks,
Greg
--
Greg Simon <grs124@psu.edu>
Newt's Cape co/Developer
http://www.netaxs.com/~weyer/newton/newtscape.html
+++++++++++++++++++++++++++
>From Jack Littleton <jackal@aimnet.com>
Date: Mon, 25 Mar 1996 19:19:05 -0800
Organization: The Windward Group
Greg Simon wrote:
> What's the proper way to find out what CTB devices (e.g., "Modem Port",
> etc) are available on a machine?
There are some routines in something called the "Communications Resource
Manager" that are used to find the number and names of serial ports. I
haven't seen any documentation, but there is an example of how to use them
in the Communications Toolbox folder in the snippets folder of the
developer cd (Tool Chest).Greg Simon wrote:
--
Jack Littleton
The Windward Group (http://www.wwg.com)
Los Gatos, CA
+++++++++++++++++++++++++++
>From mspace@netcom.com (Brian Hall)
Date: Tue, 26 Mar 1996 00:08:00 GMT
Organization: Mark/Space Softworks
grs124@psu.edu (Greg Simon) writes:
>What's the proper way to find out what CTB devices (e.g., "Modem Port",
>etc) are available on a machine?
>or, is "Inside the Macintosh Communications Toolbox" online anywhere?
>Thanks,
See the Communications Resource Manager calls documented in that manual.
(It is not online, you'll need to buy the book).
--
__________________________________________________________________________
Brian Hall, Mark/Space Softworks Internet: mspace@netcom.com
Communicate, PageNOW!, CTB Tools AppleLink, AOL: MARKSPACE
Goodies at <ftp://ftp.netcom.com/pub/ms/mspace>
+++++++++++++++++++++++++++
>From russ@aol.com (Russ)
Date: 27 Mar 1996 11:23:34 -0500
Organization: America Online, Inc. (1-800-827-6364)
Greg Simon wrote:
> What's the proper way to find out what CTB devices (e.g., "Modem Port",
> etc) are available on a machine?
On the Apple Web site there is a code snippet that shows exactly how to do
this, the URL is:
http://dev.info.apple.com/source/code/Snippets/Communications_Toolbox/Find
SerialPorts/ReadMe.html
I used code based on this in an application of mine and it works fine.
- ------------------------------------------------
Russell Easby-Smith russ@aol.com
all spelling mistakes contained here are copyright
1996 Russell Easby-Smith, all rights reserved. Any
use of them without explicit permission is a violation
of copyright laws.
- --------------------------------------------------
---------------------------
>From Britt.Bolen@Kiski.Org (Britt Bolen)
Subject: How to make an app scriptable
Date: Wed, 20 Mar 1996 14:50:04 -0500
Organization: BB's Custom Software
How does one begin to make an app scriptable? I couldn't find anything in
the old IM books, so I was wondering if someone could point me in the
right direction to make my app scriptable. Thanks
Britt
--
Britt.Bolen@Kiski.Org
"And so we beat on, boats against the current, borne back ceaselessly into the past."
F. Scott Fitzgerald
+++++++++++++++++++++++++++
>From pottier@chaland.ens.fr (Francois Pottier)
Date: 21 Mar 1996 08:31:25 GMT
Organization: Ecole Normale Superieure, Paris
In article <Britt.Bolen-2003961450040001@beck_17s.citynet.net>,
Britt Bolen <Britt.Bolen@Kiski.Org> wrote:
>How does one begin to make an app scriptable? I couldn't find anything in
>the old IM books, so I was wondering if someone could point me in the
>right direction to make my app scriptable. Thanks
It isn't easy. The whole thing is rather neatly thought out but there
is a lot to learn.
The main reference book is NIM:IAC (Inter-Application Communication),
and you will also need the Apple Event Registry which contains a list
of standard events.
Then, there have many interesting articles on this topic in past
issues of Develop (from 17 or so up to now). You should check them
out. Finally, you should probably use a framework which will help you
handle the AEOM - one of the Develop articles gives one and explains
it, there is another one embedded in PowerPlant (read the source code
in the Apple Events folder).
I hope this helps,
--
Francois Pottier
Francois.Pottier@ens.fr
Francois.Pottier@inria.fr
http://www.eleves.ens.fr:8080/home/pottier/
+++++++++++++++++++++++++++
>From mortensen@embl-heidelberg.de (Peter Mortensen)
Date: 28 Mar 1996 21:40:13 GMT
Organization: EMBL
In article <4ir44t$rc0@nef.ens.fr>
pottier@chaland.ens.fr (Francois Pottier) writes:
>>How does one begin to make an app scriptable? I couldn't find anything in
>>the old IM books, so I was wondering if someone could point me in the
>>right direction to make my app scriptable. Thanks
>Then, there have many interesting articles on this topic in past
>issues of Develop (from 17 or so up to now). You should check them
>out. Finally, you should probably use a framework which will help you
For design of the script interface (not the implementation) these fine
articles will help you make your application's script interface at
least as good as any current commmercial application's script
interface:
Cal Simone. Develop. Issue 21, March 1995.
Designing a Scripting Implementation. Page 48-72.
Cal Simone. Develop. Issue 22, June 1995. ACCORDING TO SCRIPT column.
Scripting Quandaries. Page 81-82.
Cal Simone. Develop. Issue 23, September 1995. ACCORDING TO SCRIPT
column.
Thinking About Dictionaries. Page 90-93.
Regards,
Peter Mortensen
- ----------------------------------------------------------------------
Peter Mortensen, E-mail:
mortensen@embl-heidelberg.de
Software Engineer, M.Sc.E.E. FAX: +49 (0)6221 387
306
European Molecular Biology Laboratory (EMBL) Phone: +49 (0)6221 387
560
http://www.mann.embl-heidelberg.de/PPG/PersonalPages/PeterM/PeterM.html
---------------------------
>From Manuel Veloso <veloso@apix.com>
Subject: Macsbug 6.5.3 slower at stepping?
Date: Tue, 26 Mar 1996 00:34:36 GMT
Organization: Active Paper, Inc.
I and a couple of others at the office are using Macsbug 6.5.3
now, and have noticed a large slowdown in the step/trace times on
our machines. It takes almost a second (well, a lot more time) to
step/trace than in 6.5.2.
Has anyone else noticed? Both of us are running macsbug off
of our internal video, with the other monitor running off a
card.
- ---------------------------------------
Manny Veloso Digital Plumber
Active Paper, Inc. http://www.apix.com
- ---------------------------------------
4%
+++++++++++++++++++++++++++
>From mvgfr@netcom.com (Marc Farnum Rendino)
Date: Tue, 26 Mar 1996 15:02:29 GMT
Organization: mvgfr
On Tue, 26 Mar 1996 00:34:36 GMT, Manuel Veloso (veloso@apix.com)
wrote (<DouMxo.D0A@sig.net>):
> I and a couple of others at the office are using Macsbug 6.5.3
> now, and have noticed a large slowdown in the step/trace times
FWIW, I noticed a blurb in the release notes about showing more info
on environment changes (eg: err codes) while stepping.
- Marc
+++++++++++++++++++++++++++
>From jumplong@aol.com (Jump Long)
Date: 27 Mar 1996 02:05:41 -0500
Organization: America Online, Inc. (1-800-827-6364)
Manny Veloso wrote:
>I and a couple of others at the office are using Macsbug 6.5.3
>now, and have noticed a large slowdown in the step/trace times
>on our machines. It takes almost a second (well, a lot more
>time) to step/trace than in 6.5.2.
>
>Has anyone else noticed? Both of us are running macsbug off of
>our internal video, with the other monitor running off a card.
Manny, are you by chance debugging Magic Cap code in the Magic Cap
simulator? :-) If so, then I think I know the problem and a solution.
When debugging a Magic Cap program using the Magic Cap simulator, you've
got a *very* large chunk of 68K code, it's in one *big* Macintosh memory
block, and it has *lots* of MacsBug symbols.
With MacsBug 6.5.3, support for native PowerPC debugging was improved a
lot, but it made searching for symbols in a memory block slower on Power
Macintosh systems because each block is searched for both 68K and CFM
symbols. With smaller memory blocks, you'll probably never notice the
slowdown. However, when you're dealing with a memory block the size you
get with the Magic Cap simulator, the slow-down is very noticable.
What can you do? Make MacsBug think it's running on a 68K system. To do
that, you remove the 'mxnx' resource in MacsBug. Note that this means that
you lose all PowerPC debugging enhancements in MacsBug, but if you're only
debugging 68K code, that probably won't bother you much.
I suggested to Jim Murphy righ that he add a MacsBug command to tell it to
only look for 68K symbols. I'll check again to see if that can be added in
the future.
- Jim Luther
jumplong@aol.com
<http://members.aol.com/JumpLong/>
+++++++++++++++++++++++++++
>From Manuel Veloso <veloso@apix.com>
Date: Thu, 28 Mar 1996 22:35:48 GMT
Organization: Active Paper, Inc.
In article <4japc5$3cu@newsbf02.news.aol.com> Jump Long, jumplong@aol.com
writes:
>
>Manny, are you by chance debugging Magic Cap code in the Magic Cap
>simulator? :-) If so, then I think I know the problem and a solution.
Why yes!
>What can you do? Make MacsBug think it's running on a 68K system. To do
>that, you remove the 'mxnx' resource in MacsBug. Note that this means that
>you lose all PowerPC debugging enhancements in MacsBug, but if you're only
>debugging 68K code, that probably won't bother you much.
Will do. I guess, though, I won't be able to tell if a crash was due to
something I was doing in the simulator or some random system death :P.
- ---------------------------------------
Manny Veloso Digital Plumber
Active Paper, Inc. http://www.apix.com
- ---------------------------------------
cranking towards Sunnyvale
waiting to be shipped? :P
+++++++++++++++++++++++++++
>From roy@earthlight.co.nz (Roy Ward)
Date: Sun, 31 Mar 1996 21:49:23 +1200
Organization: none
In article <4japc5$3cu@newsbf02.news.aol.com>,
jumplong@aol.com (Jump Long) wrote:
>What can you do? Make MacsBug think it's running on a 68K system. To do
>that, you remove the 'mxnx' resource in MacsBug. Note that this means that
>you lose all PowerPC debugging enhancements in MacsBug, but if you're only
>debugging 68K code, that probably won't bother you much.
Or depending on what you are doing, use 'sx' to toggle off the symbols.
That's what I do in very big code blocks with 6.5.2, and it is a massive
speed increase.
Roy.
---------------------------
>From DaveZ@mailbag.com (David B. Zwiefelhofer)
Subject: NewGWorld Memory Leak?
Date: Fri, 08 Mar 1996 17:51:19 -0500
Organization: Utility Reduction Specialists, Inc.
I've been using ZoneRanger 1.6 to track down some memory leaks and noticed
that NewGWorld allocates 26 handles, but DisposeGWorld only deallocates
24. Anyone have any idea why? The only bit I set in the flags is
noNewDevice.
Thanks,
Dave
--
David B. Zwiefelhofer
Utility Reduction Specialists, Inc.
1605 Monroe Street, Suite 110
Madison, WI 53211-2052
(608) 258-8965
(608) 258-9686 FAX
+++++++++++++++++++++++++++
>From cameron_esfahani@powertalk.apple.com (Cameron Esfahani)
Date: Wed, 20 Mar 1996 21:52:00 GMT
Organization: Apple Computer, Inc.
This memory leak has been fixed in 7.5.3.
Cameron Esfahani
+++++++++++++++++++++++++++
>From boxtop@aris.com (boxtop)
Date: 22 Mar 1996 04:23:36 GMT
Organization: BoxTop Software
In article <cameron_esfahani-2003961352000001@a17-202-33-245.apple.com>
cameron_esfahani@powertalk.apple.com (Cameron Esfahani) writes:
> This memory leak has been fixed in 7.5.3.
>
> Cameron Esfahani
@*%^!! I've been looking for this same leak thinking it was my code!
Nice to know it wasn't, but since the app in question relies heavily on
GWorlds the amount of the leaking going on adds up to a significant
amount and it not being my fault is little consolance. Short of
rewriting the thing from the ground up the high reliance on GWorlds
can't go so is there any way to get ahold of said left over 2 handles
to dispose of them manually?? Or would that divuldge some great
mystical secret of the GWorld?
Travis Anton,
-- BoxTop Software
boxtop@aris.com | http://www.aris.com/boxtop | ftp://aris.com/boxtop
________________ "Making the tools that make the web." ________________
ProJPEGv1.0.1 a Mac Photoshop file-format plug-in brings progressive
JPEG
support to your favorite image processing program with 'open and save'
ease and, makes significant improvements over Photoshop's built in JPEG
support that not only let you make progressive JPEGs but also let you
make the smallest baseline JPEGs possible.
PhotoGIFv1.1.4 the only file-format plug-in support for transparent and
interlaced GIF89a (And interlaced 87a's) files and unquestionably the
best tool for creating GIF graphics with Photoshop. "The Net Magazine"
called it "invaluable". Take a look and find out for yourself why.
+++++++++++++++++++++++++++
>From tonyn@tiac.net (Tony Nelson)
Date: Wed, 27 Mar 1996 21:47:55 -0500
Organization: The Internet Access Company
In article <4ita08$k6j@NNTP.MsState.Edu>, boxtop@aris.com (boxtop) wrote:
> ... Short of
> rewriting the thing from the ground up the high reliance on GWorlds
> can't go so is there any way to get ahold of said left over 2 handles
> to dispose of them manually?? Or would that divuldge some great
> mystical secret of the GWorld?
Since the leak happens when _NewGWorld is called, why not just leave the
GWorld around and use it again? If it takes too much memory, you can call
_AllowPurgePixels.
____________________________________________________________________
TonyN.:' tonyn@tiac.net
'
+++++++++++++++++++++++++++
>From AppleGG@lamg.com (Gordon Apple)
Date: 31 Mar 1996 11:24:03 GMT
Organization: Los Angeles Macintosh Group BBS
Eric Shapiro,Shapiro@AOL.com,Internet writes:
The nice thing about this method is that it works really well for raw
animation files or digitized graphics because you control the rowBytes
value instead of having NewGWorld assign you one. For some of my old code,
this allows me to read in several animation frames directly into a single
big buffer and just manipulate the baseAddr for each frame. (You *could*
do this with GWorlds, but you'd be mucking with something you're not
supposed to muck with).
- -----------------------------------------
Along that line, I'm using GWorlds for a 4-bit offscreen and am storing
the rseults in a file. Because I was not sure exactly how the bytes align, I
write out one big block for the image, but before that I write out the value
of rowbytes. When I read it in, I get the rowbytes of the GWorld on the
maching that is doing the reading so that I can read one row at a time and
adjust for differences in row-bytes.
I started doing this when I realized that the PCI macs have an extra
16-bytes per row instead of the extra 4-bytes I was used to in older Macs.
(Side Note:)
If you are reading a CTable from a resource for use for your GWorld (or
any other reason for that matter) BEWARE THE 7.5.3 NATIVE RESOURCE MANAGER.
Be sure you use GetCTable, not GetResource. The latter won't work anymore
for this purpose. (Trust me.)
G. Gordon apple, PhD
Advanced Communications Engineering, Inc.
Redondo Beach, CA
+++++++++++++++++++++++++++
>From Shapiro@AOL.com (Eric Shapiro)
Date: Fri, 29 Mar 1996 11:49:17 -0500
Organization: Rock Ridge Enterprises
> > In article <DaveZ-0803961751190001@msn_7_3.binc.net>, DaveZ@mailbag.com
> > (David B. Zwiefelhofer) wrote:
> >
> > > I've been using ZoneRanger 1.6 to track down some memory leaks and noticed
> > > that NewGWorld allocates 26 handles, but DisposeGWorld only deallocates
> > > 24. Anyone have any idea why? The only bit I set in the flags is
> > > noNewDevice.
You can "roll your own" GWorlds. It isn't simple, except that there's a
tech note that explains exactly how to do it.
You create a GDevice and CGrafPort, allocate the PixMap, etc, etc.
The nice thing about this method is that it works really well for raw
animation files or digitized graphics because you control the rowBytes
value instead of having NewGWorld assign you one. For some of my old code,
this allows me to read in several animation frames directly into a single
big buffer and just manipulate the baseAddr for each frame. (You *could*
do this with GWorlds, but you'd be mucking with something you're not
supposed to muck with).
-Eric
--
Eric Shapiro
Rock Ridge Enterprises
shapiro@aol.com
---------------------------
>From mars@netcom.com (Darren Giles)
Subject: Optimizing RGB pixel operations on PPC?
Date: Mon, 11 Mar 1996 22:21:33 GMT
Organization: Terran Interactive
I'm doing a lot of work with 32-bit bitmap manipulation on a PowerPC, and
I'm trying to find the most optimal way to perform pixel manipulations.
The code snippet below illustrates my current approach. It takes a series
of pixels, and adjusts the red & green values.
There are a number of smallish things to play with (like whether to have
intermediate values or just one big formula) -- but what I'm wondering is,
is there a substantially better approach that I'm overlooking?
#define RED_BYTE(x) (x>>16 & 0x000000ff)
#define GREEN_BYTE(x) (x>>8 & 0x000000ff)
#define BLUE_BYTE(x) (x & 0x000000ff)
while (src_addr < last_src_addr) {
// read source pixel
long pixel_value= *src_addr++;
// adjust brightness of red + green channels
long red= RED_BYTE(pixel_value) * red_scale;
long green= RED_BYTE(pixel_value) * green_scale;
long blue= RED_BYTE(pixel_value);
// write destination pixel
*dst_addrr++ = red << 16 | green << 8 | blue;
}
Any suggestions greatly appreciated!
- Darren
==========================================================================
Darren Giles, Technical Director Terran Interactive
For info on Cleaner QuickTime compression, visit http://www.Terran-Int.com
+++++++++++++++++++++++++++
>From kptben@aol.com (KPT Ben)
Date: 12 Mar 1996 22:22:50 -0500
Organization: America Online, Inc. (1-800-827-6364)
ian@five-d.com (Ian Kemmish) wrote:
>On a RISC (any RISC....) you want to avoid integer multiplies like the
plague.
>Do all your calculations in floating point up until after the last
multiply,
>and then (and only then) convert to integers. Even on the old R2000, a
>floating multiply was nearly three times as fast as an integer multiply,
and
>things have generally got worse since then....
Not necessarily true. For an operation such as multiplying two RGB pixels
using integer math, we'd have code something like
uint32 PixMult(uint32 p1, uint32 p2) { // uint32 == unsigned long
uint32 r1,g1,b1;
uint32 r2,g2,b2;
uint32 r,g,b;
r1 = RedByte(p1); g1 = GreenByte(p1); b1 = BlueByte(p1); // unpack
first pixel
r2 = RedByte(p2); g2 = GreenByte(p2); b2 = BlueByte(p2); // unpack
second pixel
r = (r1 * r2) >> 8; // multiply channels
g = (g1 * g2) >> 8;
b = (b1 * b2) >> 8;
return r << 16 | g << 8 | b; // pack destination pixel
}
which involves 6 instructions to unpack the components, three integer
multiply/shifts, and four instructions to reassemble the result.
On a PPC601, this takes a total of 25 cycles. On a 604, it can be done in
about 10 cycles.
To put this in perspective, converting a SINGLE integer value to
floating-point and back on PPC takes about 8-10 cycles. Here you'd have to
convert SIX values to floating-point (then convert three back to integer),
a HIDEOUS amount of overhead to get to the floating-point multiplies
(which on the 604 are the same speed as integer multiplies; 1-3 cycles
faster than integer on the 601).
The Moto 601/604 PowerPC manuals are a very useful read on this topic.
Happy coding,
--
Ben Weiss
Senior Software Engineer
MetaTools Inc. (formerly HSC Software)
+++++++++++++++++++++++++++
>From kptben@aol.com (KPT Ben)
Date: 12 Mar 1996 02:11:24 -0500
Organization: America Online, Inc. (1-800-827-6364)
mars@netcom.com (Darren Giles) wrote:
>I'm doing a lot of work with 32-bit bitmap manipulation on a PowerPC, and
>I'm trying to find the most optimal way to perform pixel manipulations.
>
>The code snippet below illustrates my current approach. It takes a
series
>of pixels, and adjusts the red & green values.
>
>There are a number of smallish things to play with (like whether to have
>intermediate values or just one big formula) -- but what I'm wondering
is,
>is there a substantially better approach that I'm overlooking?
>#define RED_BYTE(x) (x>>16 & 0x000000ff)
>#define GREEN_BYTE(x) (x>>8 & 0x000000ff)
>#define BLUE_BYTE(x) (x & 0x000000ff)
>
>
>while (src_addr < last_src_addr) {
> // read source pixel
> long pixel_value= *src_addr++;
>
> // adjust brightness of red + green channels
> long red= RED_BYTE(pixel_value) * red_scale;
> long green= RED_BYTE(pixel_value) * green_scale;
> long blue= RED_BYTE(pixel_value);
>
> // write destination pixel
> *dst_addrr++ = red << 16 | green << 8 | blue;
>}
What type are the values red_scale and green_scale? if they're
floating-point, you'll take a huge hit here.
Good luck,
--
Ben Weiss
Senior Software Engineer
MetaTools Inc. (formerly HSC Software)
+++++++++++++++++++++++++++
>From Paul Tuckfield <c11533@detroitedison.com>
Date: Wed, 13 Mar 1996 11:34:31 -0500
Organization: Detroit Edison Co.
On Tue, 12 Mar 1996, David Matiskella wrote:
> On 12 Mar 1996, KPT Ben wrote:
>
> > mars@netcom.com (Darren Giles) wrote:
> >
> > >I'm doing a lot of work with 32-bit bitmap manipulation on a PowerPC, and
> > >I'm trying to find the most optimal way to perform pixel manipulations.
. . .
> > >is there a substantially better approach that I'm overlooking?
> >
> > >#define RED_BYTE(x) (x>>16 & 0x000000ff)
> > >#define GREEN_BYTE(x) (x>>8 & 0x000000ff)
> > >#define BLUE_BYTE(x) (x & 0x000000ff)
> > >
> > >
> > >while (src_addr < last_src_addr) {
> > > // read source pixel
> > > long pixel_value= *src_addr++;
> > >
> > > // adjust brightness of red + green channels
> > > long red= RED_BYTE(pixel_value) * red_scale;
> > > long green= RED_BYTE(pixel_value) * green_scale;
> > > long blue= RED_BYTE(pixel_value);
> > >
> > > // write destination pixel
> > > *dst_addrr++ = red << 16 | green << 8 | blue;
> > >}
> >
> > What type are the values red_scale and green_scale? if they're
> > floating-point, you'll take a huge hit here.
> I second Ben point that you most likely want to be doing this as a fixed
> point calcuation if possible. Otherwise the time to convert and int to a
Maybe I'm missing something, but they appear to be integers to me based on
context.(I thought the floting point types were "float" and "double" in C?)
Also, I think your red and green channels need to be masked after the
scailing, so that bits in the green cannel dont "spillover" into the
red channel when > 255, likewise with red spilling over into the alpha
channel.
Anyway I think the big thing is to move the calculations that are
constants out of the loop rather than recalculate each time. Also avoid
extra copies to temp buffers when possible:
// these were done *every* iteration in your loop, now just once
shifted_red_scale =red_scale <<16 & 0x00FF0000 ;
shifted_green_scale=green_scale<<8 & 0x0000FF00 ;
while (src_addr < last_src_addr){
*dst_addr++=(((*src_addr & 0x00FF0000)*shifted_red_scale) & 0x00FF000)
| (((*src_addr & 0x0000FF00)*shifted_green_scale) & 0x0000FF00)
| (*src_addr & 0xFF0000FF); //preserve alpha and blue chan.
src_addr++;
}
I'm a bit weak on order of operations, but you should be able to put the
src_addr++ in either the first or last multiply saving a C statement, and
possibly cycles as well if there is a postincrement type access on ppc.
(an associate of mine has just informed me that postincrement order is
not defined if you stuck it inside the calculation, so maybe you need
to leave it where it is)
If I've over parenthesized, it's for clarity and shouldn't cause
a performance hit in the compiler, since if you were an order of operations
whiz, and didn't use parens, the object code should be the same anyway (?)
I think the next step would be trying to analyze dependencies in this
statement so as to optimize for the ppc pipeline and superscalar
architecture.
That is, you may want to bust this back out into three channels, each
channel result is a register, then or the registers at the end . playing
with the order in which you scale the channels, then use the results in
the final oring, might optimize pipeline dependencies (?) and avoid a
possible stall (?). Also might allow superscalars to dispatch two
instructions (?) en route to the result.
+++++++++++++++++++++++++++
>From verec@micronet.fr (Jean-Francois Brouillet)
Date: Tue, 12 Mar 1996 17:28:19 +0100
Organization: Francenet -- Paris, France
In article <mars-1103961426480001@192.0.2.1>, mars@netcom.com (Darren
Giles) wrote:
>I'm doing a lot of work with 32-bit bitmap manipulation on a PowerPC, and
>I'm trying to find the most optimal way to perform pixel manipulations.
>
>The code snippet below illustrates my current approach. It takes a series
>of pixels, and adjusts the red & green values.
>
>There are a number of smallish things to play with (like whether to have
>intermediate values or just one big formula) -- but what I'm wondering is,
>is there a substantially better approach that I'm overlooking?
>
>
>
>#define RED_BYTE(x) (x>>16 & 0x000000ff)
>#define GREEN_BYTE(x) (x>>8 & 0x000000ff)
>#define BLUE_BYTE(x) (x & 0x000000ff)
>
>
>while (src_addr < last_src_addr) {
> // read source pixel
> long pixel_value= *src_addr++;
>
> // adjust brightness of red + green channels
> long red= RED_BYTE(pixel_value) * red_scale;
> long green= RED_BYTE(pixel_value) * green_scale;
> long blue= RED_BYTE(pixel_value);
>
> // write destination pixel
> *dst_addrr++ = red << 16 | green << 8 | blue;
>}
>
>Any suggestions greatly appreciated!
>
>- Darren
>
>==========================================================================
>Darren Giles, Technical Director Terran Interactive
>For info on Cleaner QuickTime compression, visit http://www.Terran-Int.com
Just my two cents...
what about :
while (src_addr < last_src_addr) {
// get a pointer on alpha byte, increment src_addr by four bytes
unsigned char *p = (unsigned char *) ((long *) src_addr++);
++p; // skip alpha chan.
*p *= red_scale;
++p; // go next chan.
*p *= green_scale;
// no need to do anything with blue chan, so just let the next
// iteration reajust ``p'' on next pixel boundary.
}
I didn't test, and don't have a C ref manual handy but perhaps you could
even try something like :
(*++p) *= red_scale;
(*++p) *= green_scale;
With an heavy optimizing compiler (and provided that this is correct C
code which does what I suppose it does) you may get vast improvments ???
--
Jean-Francois Brouillet verec@micronet.fr
Macintosh Software Developer verecundus@eworld.com
+++++++++++++++++++++++++++
>From David Matiskella <matiskel@aa.washington.edu>
Date: Tue, 12 Mar 1996 09:47:23 -0800
Organization: University of Washington
On 12 Mar 1996, KPT Ben wrote:
> mars@netcom.com (Darren Giles) wrote:
>
> >I'm doing a lot of work with 32-bit bitmap manipulation on a PowerPC, and
> >I'm trying to find the most optimal way to perform pixel manipulations.
> >
> >The code snippet below illustrates my current approach. It takes a
> series
> >of pixels, and adjusts the red & green values.
> >
> >There are a number of smallish things to play with (like whether to have
> >intermediate values or just one big formula) -- but what I'm wondering
> is,
> >is there a substantially better approach that I'm overlooking?
>
> >#define RED_BYTE(x) (x>>16 & 0x000000ff)
> >#define GREEN_BYTE(x) (x>>8 & 0x000000ff)
> >#define BLUE_BYTE(x) (x & 0x000000ff)
> >
> >
> >while (src_addr < last_src_addr) {
> > // read source pixel
> > long pixel_value= *src_addr++;
> >
> > // adjust brightness of red + green channels
> > long red= RED_BYTE(pixel_value) * red_scale;
> > long green= RED_BYTE(pixel_value) * green_scale;
> > long blue= RED_BYTE(pixel_value);
> >
> > // write destination pixel
> > *dst_addrr++ = red << 16 | green << 8 | blue;
> >}
>
> What type are the values red_scale and green_scale? if they're
> floating-point, you'll take a huge hit here.
>
> Good luck,
>
> --
> Ben Weiss
> Senior Software Engineer
> MetaTools Inc. (formerly HSC Software)
I second Ben point that you most likely want to be doing this as a fixed
point calcuation if possible. Otherwise the time to convert and int to a
float, convert a float to an int and store and load the value while most
likely take as much time as the rest of the calculations. Other than that
you might want to look at the assembly code of the procedure. the
RED_BYTE macro should only require 1 instruction if the optimizer is any
good. Similiar using preincrement instead of postincrement maps better to
the powerpc instruction set. A really code compiler should do this for
you but I have not been too impressed with the current state of the art
powerpc compilers.
David Matiskella
matiskel@aa.washington.edu
+++++++++++++++++++++++++++
>From ian@five-d.com (Ian Kemmish)
Date: 12 Mar 1996 18:21:24 GMT
Organization: At home with Ian
In article <mars-1103961426480001@192.0.2.1>, mars@netcom.com says...
>There are a number of smallish things to play with (like whether to have
>intermediate values or just one big formula) -- but what I'm wondering is,
>is there a substantially better approach that I'm overlooking?
>while (src_addr < last_src_addr) {
> // read source pixel
> long pixel_value= *src_addr++;
>
> // adjust brightness of red + green channels
> long red= RED_BYTE(pixel_value) * red_scale;
> long green= RED_BYTE(pixel_value) * green_scale;
> long blue= RED_BYTE(pixel_value);
>
> // write destination pixel
> *dst_addrr++ = red << 16 | green << 8 | blue;
>}
>
On a RISC (any RISC....) you want to avoid integer multiplies like the plague.
Do all your calculations in floating point up until after the last multiply,
and then (and only then) convert to integers. Even on the old R2000, a
floating multiply was nearly three times as fast as an integer multiply, and
things have generally got worse since then....
If you really are constrained to do this operation on a pre-existing raster,
then use a lookup table to do the multiply. Also, on most RISCs, a byte read
and byte write are faster than a word read followed by a shift-and-mask. You
won't suffer from doing consecutive byte writes for the red and green pixels
on any system with decent write buffers.
============================================================================
Ian Kemmish 18 Durham Close, Biggleswade, Beds SG18 8HZ
ian@five-d.com Tel: +44 1767 601 361 Fax: +44 1767 312 006
Info on Jaws and 5D's other products on http://www.five-d.com/5d
============================================================================
`The customer is King, but the proprietor is God'
+++++++++++++++++++++++++++
>From David Matiskella <matiskel@aa.washington.edu>
Date: Wed, 13 Mar 1996 09:18:33 -0800
Organization: University of Washington
On 12 Mar 1996, KPT Ben wrote:
> ian@five-d.com (Ian Kemmish) wrote:
> >On a RISC (any RISC....) you want to avoid integer multiplies like the
> plague.
> >Do all your calculations in floating point up until after the last
> multiply,
> >and then (and only then) convert to integers. Even on the old R2000, a
> >floating multiply was nearly three times as fast as an integer multiply,
> and
> >things have generally got worse since then....
>
> Not necessarily true. For an operation such as multiplying two RGB pixels
> using integer math, we'd have code something like
>
> uint32 PixMult(uint32 p1, uint32 p2) { // uint32 == unsigned long
> uint32 r1,g1,b1;
> uint32 r2,g2,b2;
> uint32 r,g,b;
>
> r1 = RedByte(p1); g1 = GreenByte(p1); b1 = BlueByte(p1); // unpack
> first pixel
> r2 = RedByte(p2); g2 = GreenByte(p2); b2 = BlueByte(p2); // unpack
> second pixel
>
> r = (r1 * r2) >> 8; // multiply channels
> g = (g1 * g2) >> 8;
> b = (b1 * b2) >> 8;
>
> return r << 16 | g << 8 | b; // pack destination pixel
> }
>
> which involves 6 instructions to unpack the components, three integer
> multiply/shifts, and four instructions to reassemble the result.
>
> On a PPC601, this takes a total of 25 cycles. On a 604, it can be done in
> about 10 cycles.
>
> To put this in perspective, converting a SINGLE integer value to
> floating-point and back on PPC takes about 8-10 cycles. Here you'd have to
> convert SIX values to floating-point (then convert three back to integer),
> a HIDEOUS amount of overhead to get to the floating-point multiplies
> (which on the 604 are the same speed as integer multiplies; 1-3 cycles
> faster than integer on the 601).
>
> The Moto 601/604 PowerPC manuals are a very useful read on this topic.
>
> Happy coding,
>
> --
> Ben Weiss
> Senior Software Engineer
> MetaTools Inc. (formerly HSC Software)
>
One other minor thing I remembered is that you want to multiply by the
smaller number. ie if your scale is a 16 bit number it should read
scale*redbyte rather than redbyte*scale. The compiler will have trouble
with an optimization like this since it has no idea of the size of the
variables.(Although it should be able to determine the size of redbtye).
As far as I know reading a word and a byte are the same speed on a
powerpc. On a 603 or 604 with there separate LSU units you probaly could
make the routine faster by reading bytes but I think it would be slower
on a 601.
David Matiskella
matiskel@aa.washington.edu
+++++++++++++++++++++++++++
>From more@stekt.oulu.fi (Jyrki Alakuijala)
Date: 14 Mar 1996 17:11:31 GMT
Organization: (none)
The following "benchmarking" is done on Alpha:
long[char] takes about 730 "clicks" on Alpha.
char * char takes about 2000 "clicks"
bitshift takes some 420 "clicks"
>On a RISC (any RISC....) you want to avoid integer multiplies like the plague.
This is simply not true any more. There are a lot of risc processors that
have fast integer multipliers. Alpha spend 3600 "clicks" on long * long and
about 5200 on double * double. float * float was around 2800. char * long
is faster than any floating point combination.
>then use a lookup table to do the multiply. Also, on most RISCs, a byte read
I agree completely. Lookup tables are fast on most architectures.
You might even want to consider a lookup table that would have
green and blue combined:
unsigned long redLookup[256];
// (redLookup uses 1024 bytes of ram)
unsigned short greenBlueLookup[65536];
// (greenBlueLookup uses 128kB of ram :-( )
Then you could use these as follows:
*dst_addrr++ = redLookup[longValue >> 16] +
greenBlueLookup[longValue & 0xffff];
In some cases it is good practice to build your bitmap correctly
from the beginning. Then you would not have any need to
travel through it again at this time. :-)
Please, let us know which approach you find fastest.
--Jyrki
+++++++++++++++++++++++++++
>From pasbesoin@pasici.pasla
Date: 18 Mar 1996 16:33:58 GMT
Organization: IConNet
How do you get the value of the RGB pixel
using GetCPixel from grafptr or do you have something better ???
+++++++++++++++++++++++++++
>From Shapiro@AOL.com (Eric Shapiro)
Date: Sun, 24 Mar 1996 14:05:57 -0500
Organization: Rock Ridge Enterprises
In article <mars-1103961426480001@192.0.2.1>, mars@netcom.com (Darren
Giles) wrote:
> I'm doing a lot of work with 32-bit bitmap manipulation on a PowerPC, and
> I'm trying to find the most optimal way to perform pixel manipulations.
While normally I try and stay away from writing PowerPC assembly
language, pixel manipulation is one case where you can really
speed up routines by using assembly.
The PowerPC architecture has a "shift w/mask" instruction that
extracts pixel values from bitmaps very quickly. You might want
to disassemble your code to see if the compiler is smart enough
to use these instructions. If not, consider assembly.
I don't think you can multiply all of the component values in
a single multiply instruction, especially since overflowing the
lower bytes will affect the values in the higher ones.
-Eric
--
Eric Shapiro
Rock Ridge Enterprises
shapiro@aol.com
---------------------------
>From mxmora@mxmdesigns.com (Matthew Xavier Mora)
Subject: UMPA Awards Last week for Nominations
Date: 31 Mar 1996 07:06:31 GMT
Organization: MXM Designs™
Announcing The Second Annual USENET Macintosh Programming Awards
UMPA 1996
sponsored by Bare Bones Software and Metrowerks
We have been getting a lot of prizes thanks to some evanglizing from
Jordan Mattson. Thanks Jordan. Keep the nominations comming in!
So the list of prizes so far is:
Every winner will get this stuff:
- UMPA T -Shirt
- UMPA Plaque.
- $100.00 Cash Prize (Oooh!)
- $100.00 APDA Gift Certificate (from Juan Bettaglio )
- A Self Paced Course from DU (from Jennifer Martin)
- One year free membership in the Associates Plus or AMP program
( Or an extension if currently enrolled from Cindy Gallie)
The things below will go to the winners of the ShareWare, Freeware,
Support and Smart friend categories only since the Commercial winner has
all this stuff anyway.
- Lots o' Symantec Stuff (includes Mac C++ and Java tools)
(from Will Iverson)
t-shirts, option for any Symantec product NFR (e.g. a choice of C++ Win,
ACT!, Norton, etc.). - Apprentice CD (From Paul Celestin )
- BBEdit and BBEdit T-shirts (From Rich Siegel)
- Metrowerks Gold CD and buch of other stuff
- QC by Onyx Technology from Devon Hubbard and Brooks Bell
- Roaster the Java Development Environment from Natural Intelligence
A big thanks to our sponsors!
So send in your nominations!
Matt
- -----------------------------------------------------------
U M P A
- -----------------------------------------------------------
It looks like its time for the Second Annual Usenet Macintosh Programming
Awards (UMPA). For those of you that have never heard of this before, last
year we created the UMPA awards to honor our peers in the Mac Programming
world. Often a program itself will get awarded but the person(s)
responsible for creating the product never get their due recognition for a
job well done. This award is to honor those in the trenches fighting the
good fight for the Macintosh.
This is the last week of nomination. I'm letting the nomination run a week
longer than normal because I'll be out of town until April 6th.
Here is a list of the categories:
Outstanding Programming for a Commercial Product.
Outstanding Programming for a Shareware Product.
Outstanding Programming for a Freeware Product
Outstanding Support of the Mac programming community. (usually from a non
programmer)
Official SmartFriend(tm) award for the most helpful c.s.m.p.* net citizen.
Here is a list of the current nominees (Remember we are nominating the
programmers not the product so please include the name of the
programmer(s)):
Outstanding Programming for a Commercial Product:
1. Rich Siegel for BBEdit
2. Jordan Zimmerman for QuickView/MPTA
3. Alan Bird for OneClick (WestCode Software)
4. Devon Hubbard and Brooks Bell for QC
5. Jud Spencer for Claris Emailer
6. Marcel Achim for CW Pascal compiler
7. Claris team (Tom Hoke, Scott Holdaway, Scott Lindsey, Bob Hearn, Ben
Chang, Bruce Hammond, Mate Gross) for ClarisWorks
8. Jason Jones (Bungie Software) for Marathon.
9. Mark Adams, Ken Cobb, Jim Hamilton, Mike Korte, Robert Thurman, Ken
Offer and Tim Hall (GraceLAN Network Management Series)
10. Kai Krause and Ben Wiess for their amazing code.
11. Brian Sutter, the author of Installer VISE
12. Brian Hall(?) of Mark/Space for PageNow!
13. Richard Zulch, author of Retrospect and Retrospect Remote
14. John McEnerny of Metrowerks for the CW C++ compiler.
15. Eric Scouten for Constructor
Outstanding Programming for a Shareware Product:
1. Mitch Jones for Snitch
2. Gilles Berkovitch for Glidel
3. Leonard Rosenthol, Marshall Clow and Crew for Stuffit products.
4. David Waring for Swoop from Ambrosia
5. Kurt Piersol, Jens Alfke, Jon Pugh, and the rest of
the OpenDoc team for best programming for a shareware product OpenDoc
6. Andrew Welch for all his cool games
7. Text-Edit Plus by Tom Bender
8. Style by Marco Piavonelli
9. Greg Landweber and Ed Voas for Aaron.
10. Francois Pottier for Decor.
11. John Brochu for CalcWorks.
12. Jerry Aman for PageSpinner
13. Alberto Ricci for SoundEffects
14. Ted Leckie, Tom Andersen, Peter Hanson for StarryNight
15. Peter Keleher - Alpha text editor
16. Richard C Cardona for Click! There it is
17. Samuel, David and Andreas Rydh for Note Pad Deluxe
18. Scott Sykes for Netscape Defrost
Peter Lewis respectfully declines the nomination.
Outstanding Programming for a Freeware Product:
1. Michael Hecht for ResCompare
2. Steve Dagley, Richard Reynolds, and Co. for FreePPP.
3. Lindsay Davies and Carles Bellver for HTML tools for BBEdit
4. Quinn the Eskimo & Peter for IC
5. John Norstad!
6. Aaron Giles for JPEGView
7. Matthias Neeracher for MacPerl
8. Chris W Johnson for the SIVC system
9. Rick Holzgrafe for The Tilery
10. Chad Magendanz for ShrinkWrap.
11. The MicroMat team for TechTool.
12. Marco Piovanelli for WASTE Text Engine
13. Brian Clark - Yet Another NewsWatcher
14. Wayne Rasband for "NIH-Image"
15. James Thomson for his coolware DragThing
Outstanding Support of the Mac programming community:
1. The folks at MetroWerks
2. Neil Ticktin of MacTech Magazine
3. Natural Intelligence , for Roaster.
4. Ron Liechty (MWRon), for his continually outstanding support at c.s.m.p.cw
5. John Norstad!
6. Paul Celestin for Apprentice and his other great CDs 7. Jim Luther
7. Ric Ford and Rick LePage of Macintouch.
8. Dan Crevier
9. Ken Long
Official SmartFriend(tm) award :
1. Jon Pugh, for many of his insights on AppleScript
2. dEVoN Hubbard
3. Pete Gontier
4. Garry Hornbuckle, for his great help with OT's startup hiccups
5. Quinn, the Eskimo for OT support
6. Jim Luther for his file system knowledge
8. Tim Olson for is PowerPC knowledge
9. Lars Farm
10. Greg Robbins at Apple
The list of final nominees is chosen by the number times that programmer
was nominated. So if you want your favorite programmer to make the
nomination cut, Send in his/her name. Since this is the last post until
we start voting, sending in a new name of a programmer probably won't do
much good but you still can if you like.
Since this award is supposed to be recognition from our peers, You will
need to answer a Macintosh programming question to have a valid
nomination.
The first question is:
What is the recommended sleep value for WaitNextEvent for a foreground
Application. :-)
So send me your nominations <mailto:mxmora@mxmdesigns.com> with what you
"think" is the correct answer to the above question and I will keep
updating the nomination list. Here is the URL for the UMPA home page.
<http://www.best.com/~mxmora/UMPA.html>
If you would like to donate prizes to this cause, please send me email
<mailto:mxmora@mxmdesigns.com>. Last year we collected 5 prizes for each
category. This year I think we should just collect 4 prizes since the
"Outstanding Programming for a Commercial Product" winner already had all
the stuff we collected last year. The award,t-shirt, plaque, cash and
other goodies is probably honor enough.
Thanks for listening and good luck to the nominees!
Xavier
---------------------------
>From jumplong@aol.com (Jump Long)
Subject: [ANN] MoreFiles v1.4.2 now available
Date: 26 Mar 1996 01:03:14 -0500
Organization: America Online, Inc. (1-800-827-6364)
MoreFiles is a collection of high-level routines written over the last
couple of years to answer File Manager questions developers have sent to
Apple Developer Technical Support and to answer questions on various
online services and the internet. The routines have been tested (but not
stress-tested), documented, code-reviewed, and used in both my own
programs and in many commercial products.
MoreFiles version 1.4.2, is now available today at:
ftp://members.aol.com/JumpLong/MoreFiles_1.4.2.sea.hqx
MoreFiles version 1.4.2 will also be submitted for release through various
other means including:
Apple Computer (Developer CD, ftp, AppleLink, etc.)
America Online (Macintosh Developers Forum)
CompuServe (Macintosh Developers Forum)
macgifts@mac.archive.umich.edu
Since I have no control over those means of delivery, they'll show up when
they show up...
Enjoy!
- Jim Luther
jumplong@aol.com
<http://members.aol.com/JumpLong/>
________________________________________
Here are the release notes for MoreFiles 1.4.2:
v1.4.2 3/25/96
New Routines:
* Added FSpResolveFileIDRef to MoreFiles.
* Added GetIOACUser and FSpGetIOACUser to MoreFilesExtras. These routines
let you get a directory's access privileges for the current user.
* Added bit masks, macros, and function for testing ioACUser values to
MoreFilesExtras.h and MoreFilesExtras.p.
* Added GetVolumeInfoNoName to MoreFilesExtras to put common calls to
PBHGetVInfo in one place. Functions that call GetVolumeInfoNoName are: (in
DirectoryCopy.c) PreflightDirectoryCopySpace, (in FileCopy.c)
PreflightFileCopySpace, (in MoreFilesExtras.c) DetermineVRefNum,
CheckVolLock, FindDrive, UnmountAndEject, (in Search.c) CheckVol.
* Added GetCatInfoNoName to MoreFilesExtras to put common calls to
PBGetCatInfo in one place. Functions that call GetCatInfoNoName are: (in
FileCopy.c) GetDestinationDirInfo, (in MoreDesktopMgr.c) GetCommentID, (in
MoreFilesExtras.c) GetDInfo, GetDirectoryID, CheckObjectLock.
* Added TruncPString to MoreFilesExtras. This lets you shorten a Pascal
string without breaking the string in the middle of a multi-byte
character.
* Added FilteredDirectoryCopy and FSpFilteredDirectoryCopy to
DirectoryCopy. FilteredDirectoryCopy and FSpFilteredDirectoryCopy work
just like DirectoryCopy and FSpDirectoryCopy only they both take an
optional CopyFilterProc parameter which can point to routine you supply.
The CopyFilterProc lets your code decide what files or directories are
copied to the destination. DirectoryCopy and FSpDirectoryCopy now call
through to FilteredDirectoryCopy with a NULL CopyFilterProc.
Bugs fixed:
* Fixed minor bug in GetDiskBlocks where driveQElementPtr->dQRefNum was
checked when driveQElementPtr could be NULL.
* DirectoryCopy didn't handle error conditions correctly. In some cases,
DirectoryCopy would return noErr when there was a problem and in other
cases, the CopyErrProc wasn't called and the function immediately failed.
* The result of DirectoryCopy's CopyErrProc was documented incorrectly.
Other changes and improvements:
* Added result codes to function descriptions in the C header files
(these probably aren't a perfect list of possible errors, but they should
catch most of the results you'll ever see).
* Removed most of the function descriptions in Pascal interface files
since they haven't been completely in sync with the C headers for some
time and I don't have time to keep the documentation in both places up to
date.
* Rewrote HMoveRenameCompat so it doesn't use the Temporary Items folder.
* Added parameter checking to OnLine so that it doesn't allow the
volIndex parameter to be less than or equal to 0.
* Added parameter checking to GetDirItems so that it doesn't allow the
itemIndex parameter to be less than or equal to 0.
* FSpExchangeFilesCompat now returns diffVolErr (instead of paramErr) if
the source and the destination are on different volumes.
* Changed GetDirName's name parameter to Str31 and added parameter
checking so that it doesn't allow a NULL name parameter.
* Forced errors returned by MoreDesktopMgr routines to be closer to what
would be expected if the low-level Desktop Manager calls were used.
* Added conditionalized changes from Fabrizio Oddone so that Pascal
calling conventions can be easily disabled. Disabling Pascal calling
conventions reduces the code size slightly and allows C compilers to
optimize parameter passing. NOTE: If you disable Pascal calling
conventions, you'll have to remove the "pascal" keyword from all of the
MoreFiles callbacks you've defined in your code.
* Changed DirectoryCopy so that you can copy the source directory's
content to a disk's root directory.
* Added a build script and a make file for MPW libraries.
* Added a build script for Metrowerks CodeWarrior libraries.
* Added a build script for Symantec THINK Project Manager and Symantec
Project Manager libraries.
* Renamed the Symantec and Metrowerks project files.
* Changed MoreFile's directory structure so that C headers, Pascal
interfaces, and the source code aren't in the main directory.
Thanks to Fabrizio Oddone for supplying the conditionalized changes that
optionally remove Pascal calling conventions. Thanks to Byron Han for
beating the bugs out of DirectoryCopy and for suggesting and prototyping
the changes needed for the "copy to root directory" option and the
FilteredDirectoryCopy routine in DirectoryCopy.
________________________________________
---------------------------
>From greenhut@mindspring.com (Jeff Greenhut)
Subject: [Q] Selecting a Serial Port
Date: 2 Apr 1996 22:18:45 GMT
Organization: MindSpring Enterprises
What is the correct way to select from available serial ports? I have
heard I should use the CTB, but can't find any doc or examples on the
developer reference disks(or on the Mac OS SDK disks)
I want to allow the user to select the modem's port, and wish to support
Powerbooks, PC cards...
THANKS!!!
jeff
--
Jeff Greenhut
greenhut@mindspring.com
+++++++++++++++++++++++++++
>From blob@ccnet.com
Date: Tue, 02 Apr 1996 21:28:11 -0800
Organization: CCnet Communications (510-988-7140 guest)
In article <greenhut-0204961724170001@news.mindspring.com>,
greenhut@mindspring.com (Jeff Greenhut) wrote:
>What is the correct way to select from available serial ports?
>From the comp.sys.mac.programmer FAQ at <http://www.best.com/~ckt/csmp-faq.html>
7.1) Q: How do I get at the serial ports?
A: You call OpenDriver for the names "/p.AOut" and "/p.AIn" to get at
the modem port, and "/p.BOut" and "/p.BIn" for the printer port. The
function RAMSDOpen was designed for the original Mac with 128 kB of
memory and 64 kB of ROM, and has been extinct for several years.
However, many users use their serial ports for MIDI, LocalTalk, graphic
tablets, or what have you and have installed an additional serial port
card to get more ports. What you SHOULD do as a good application is to
use the Comm Toolbox Resource Manager to search for serial resources;
this requires that the Comms Toolbox is present (true on earlier System
6 with an INIT, on later System 6 and System 7 always, as well as on
A/UX) and that you have initialized the comms resource manager. The
exact code follows (adapted from Inside Mac Comms Toolbox):
#include "CommResources.h"
OSErr
FindPorts ( Handle * portOutNames, Handle * portInNames, Handle * names,
Handle * iconHandles )
{
OSErr ret = noErr ;
short old = 0 ;
CRMRec theCRMRec , * found ;
CRMSerialRecord * serial ;
* portOutNames = NewHandle ( 0L ) ;
* portInNames = NewHandle ( 0L ) ;
* names = NewHandle ( 0L ) ;
* iconHandles = NewHandle ( 0L ) ;
while ( ! ret ) {
theCRMRec . crmDeviceType = crmSerialDevice ;
theCRMRec . crmDeviceID = old ;
found = ( CRMRec * ) CRMSearch ( ( QElementPtr ) & theCRMRec ) ;
if ( found ) {
serial = ( CRMSerialRecord * ) found -> crmAttributes ;
old = found -> crmDeviceID ;
PtrAndHand ( & serial -> outputDriverName , * portOutNames ,
sizeof ( serial -> outputDriverName ) ) ;
PtrAndHand ( & serial -> inputDriverName , * portInNames ,
sizeof ( serial -> inputDriverName ) ) ;
PtrAndHand ( & serial -> name , * names ,
sizeof ( serial -> name ) ) ;
PtrAndHand ( & serial -> deviceIcon , * iconHandles ,
sizeof ( serial -> deviceIcon ) ) ;
} else {
break ;
}
}
return err ;
}
This will create four handles with the driver names, device names and
driver icon handles for all of the available serial devices. Then let
the user choose with a pop-up menu or scrolling list, and save the
choice in your settings file.
You can use OpenDriver, SetReset, SetHShake, SetSetBuf, SerGetBuf and
the other Serial Manager functions on these drivers. To write to the
serial port, use FSWrite for synchronous writes that wait until all is
written, or PBWrite asynchronously for queuing up data that is supposed
to go out but you don't want to wait for it. At least once each time
through your event loop, you should call SerGetBuf on the in driver
reference number you got from OpenDriver, and call FSRead for that many
bytes - neither more nor less.
If you are REALLY interested in doing the right thing, you will use the
Communications Toolbox Connection Manager instead; this will give you
access to modems, direct lines, and networks of various kinds using the
same API! Great for stuff like BBSes that may be on a network as well
etc. The Comms Toolbox also provides modularized terminal emulation and
file transfer tools, although the Apple-suplied VT102 tool is pretty
lame, as is the VT102 mode of the VT320 tool.
*****
See also the "FindSerialPorts" sample code, which does the same thing, on
the tool chest developer CD.
--
"There are 3 kinds of people in the world; those who can count well enough to divide the world into 3 kinds of people, and those who can't."
---------------------------
End of C.S.M.P. Digest
**********************